diff --git a/lightningd/Makefile b/lightningd/Makefile index 22a08960e..41e0077d1 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -27,11 +27,13 @@ LIGHTNINGD_OLD_OBJS := $(LIGHTNINGD_OLD_SRC:.c=.o) LIGHTNINGD_OLD_HEADERS := $(LIGHTNINGD_OLD_SRC:.c=.h) LIGHTNINGD_OLD_LIB_SRC := \ - daemon/htlc_state.c + daemon/htlc_state.c \ + daemon/pseudorand.c LIGHTNINGD_OLD_LIB_OBJS := $(LIGHTNINGD_OLD_LIB_SRC:.c=.o) LIGHTNINGD_OLD_LIB_HEADERS := $(LIGHTNINGD_OLD_LIB_SRC:.c=.h) LIGHTNINGD_LIB_SRC := \ + lightningd/channel.c \ lightningd/channel_config.c \ lightningd/commit_tx.c \ lightningd/cryptomsg.c \ diff --git a/lightningd/channel.c b/lightningd/channel.c new file mode 100644 index 000000000..4dbcce900 --- /dev/null +++ b/lightningd/channel.c @@ -0,0 +1,592 @@ +#include "channel.h" +#include "commit_tx.h" +#include "type_to_string.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void htlc_arr_append(const struct htlc ***arr, const struct htlc *htlc) +{ + size_t n; + if (!arr) + return; + n = tal_count(*arr); + tal_resize(arr, n+1); + (*arr)[n] = htlc; +} + +/* What does adding the HTLC do to the balance for this side */ +static s64 balance_adding_htlc(const struct htlc *htlc, enum side side) +{ + if (htlc_owner(htlc) == side) + return -htlc->msatoshi; + return 0; +} + +/* What does removing the HTLC do to the balance for this side */ +static s64 balance_removing_htlc(const struct htlc *htlc, enum side side) +{ + enum side paid_to; + + /* Fulfilled HTLCs are paid to recipient, otherwise returns to owner */ + if (htlc->r) + paid_to = !htlc_owner(htlc); + else + paid_to = htlc_owner(htlc); + + if (side == paid_to) + return htlc->msatoshi; + return 0; +} + +/* Returns up to three arrays: + * committed: HTLCs currently committed. + * pending_removal: HTLCs pending removal (subset of committed) + * pending_addition: HTLCs pending addition (no overlap with committed) + */ +static void gather_htlcs(const tal_t *ctx, + const struct channel *channel, + enum side side, + const struct htlc ***committed, + const struct htlc ***pending_removal, + const struct htlc ***pending_addition) +{ + struct htlc_map_iter it; + const struct htlc *htlc; + const int committed_flag = HTLC_FLAG(side, HTLC_F_COMMITTED); + const int pending_flag = HTLC_FLAG(side, HTLC_F_PENDING); + + *committed = tal_arr(ctx, const struct htlc *, 0); + if (pending_removal) + *pending_removal = tal_arr(ctx, const struct htlc *, 0); + if (pending_addition) + *pending_addition = tal_arr(ctx, const struct htlc *, 0); + + for (htlc = htlc_map_first(&channel->htlcs, &it); + htlc; + htlc = htlc_map_next(&channel->htlcs, &it)) { + if (htlc_has(htlc, committed_flag)) { + htlc_arr_append(committed, htlc); + if (htlc_has(htlc, pending_flag)) + htlc_arr_append(pending_removal, htlc); + } else if (htlc_has(htlc, pending_flag)) + htlc_arr_append(pending_addition, htlc); + } +} + +static u64 total_offered_msatoshis(const struct htlc **htlcs, enum side side) +{ + size_t i; + u64 total = 0; + + for (i = 0; i < tal_count(htlcs); i++) { + if (htlc_owner(htlcs[i]) == side) + total += htlcs[i]->msatoshi; + } + return total; +} + +static void destroy_htlc_map(struct channel *channel) +{ + htlc_map_clear(&channel->htlcs); +} + +struct channel *new_channel(const tal_t *ctx, + const struct sha256_double *funding_txid, + unsigned int funding_txout, + u64 funding_satoshis, + u64 push_msat, + u32 feerate_per_kw, + const struct channel_config *local, + const struct channel_config *remote, + const struct pubkey *local_revocation_basepoint, + const struct pubkey *remote_revocation_basepoint, + const struct pubkey *local_payment_basepoint, + const struct pubkey *remote_payment_basepoint, + const struct pubkey *local_delayed_payment_basepoint, + const struct pubkey *remote_delayed_payment_basepoint, + enum side funder) +{ + struct channel *channel = tal(ctx, struct channel); + + channel->funding_txid = *funding_txid; + channel->funding_txout = funding_txout; + if (funding_satoshis > UINT64_MAX / 1000) + return tal_free(channel); + + channel->funding_msat = funding_satoshis * 1000; + if (push_msat > channel->funding_msat) + return tal_free(channel); + + channel->funder = funder; + channel->config[LOCAL] = local; + channel->config[REMOTE] = remote; + htlc_map_init(&channel->htlcs); + + channel->view[LOCAL].feerate_per_kw + = channel->view[REMOTE].feerate_per_kw + = feerate_per_kw; + + channel->view[funder].owed_msat[funder] + = channel->view[!funder].owed_msat[funder] + = channel->funding_msat - push_msat; + channel->view[funder].owed_msat[!funder] + = channel->view[!funder].owed_msat[!funder] + = push_msat; + + channel->view[LOCAL].commitment_number + = channel->view[REMOTE].commitment_number + = 0; + + channel->revocation_basepoint[LOCAL] = *local_revocation_basepoint; + channel->revocation_basepoint[REMOTE] = *remote_revocation_basepoint; + channel->payment_basepoint[LOCAL] = *local_payment_basepoint; + channel->payment_basepoint[REMOTE] = *remote_payment_basepoint; + channel->delayed_payment_basepoint[LOCAL] + = *local_delayed_payment_basepoint; + channel->delayed_payment_basepoint[REMOTE] + = *remote_delayed_payment_basepoint; + + channel->commitment_number_obscurer + = commit_number_obscurer(&channel->payment_basepoint[funder], + &channel->payment_basepoint[!funder]); + + tal_add_destructor(channel, destroy_htlc_map); + return channel; +} + +/* FIXME: We could cache this. */ +struct bitcoin_tx *channel_tx(const tal_t *ctx, + const struct channel *channel, + const struct pubkey *per_commitment_point, + const struct htlc ***htlcmap, + enum side side) +{ + struct bitcoin_tx *tx; + const struct htlc **committed; + /* Payment keys for @side and !@side */ + struct pubkey side_payment_key, other_payment_key; + /* Delayed payment key for @side */ + struct pubkey side_delayed_payment_key; + /* Revocation payment key for @side */ + struct pubkey side_revocation_key; + + if (!derive_simple_key(&channel->payment_basepoint[side], + per_commitment_point, + &side_payment_key)) + return NULL; + + if (!derive_simple_key(&channel->payment_basepoint[!side], + per_commitment_point, + &other_payment_key)) + return NULL; + + if (!derive_simple_key(&channel->delayed_payment_basepoint[side], + per_commitment_point, + &side_delayed_payment_key)) + return NULL; + + if (!derive_revocation_key(&channel->revocation_basepoint[side], + per_commitment_point, + &side_revocation_key)) + return NULL; + + /* Figure out what @side will already be committed to. */ + gather_htlcs(ctx, channel, side, &committed, NULL, NULL); + + tx = commit_tx(ctx, &channel->funding_txid, + channel->funding_txout, + channel->funding_msat / 1000, + channel->funder, + to_self_delay(channel, side), + &side_revocation_key, + &side_delayed_payment_key, + &side_payment_key, + &other_payment_key, + channel->view[side].feerate_per_kw, + dust_limit_satoshis(channel, side), + channel->view[side].owed_msat[side], + channel->view[side].owed_msat[!side], + committed, + htlcmap, + channel->view[side].commitment_number + ^ channel->commitment_number_obscurer, + side); + + tal_free(committed); + return tx; +} + +struct channel *copy_channel(const tal_t *ctx, const struct channel *old) +{ + struct channel *new = tal_dup(ctx, struct channel, old); + htlc_map_copy(&new->htlcs, &old->htlcs); + return new; +} + +enum channel_add_err channel_add_htlc(struct channel *channel, + enum side sender, + u64 id, + u64 msatoshi, + u32 expiry, + const struct sha256 *payment_hash, + const u8 routing[1254]) +{ + const tal_t *tmpctx = tal_tmpctx(channel); + struct htlc *htlc, *old; + s64 msat_in_htlcs, fee_msat, balance_msat; + enum side recipient = !sender; + const struct htlc **committed, **adding, **removing; + enum channel_add_err e; + const struct channel_view *view; + size_t i; + + htlc = tal(tmpctx, struct htlc); + + if (sender == LOCAL) + htlc->state = SENT_ADD_HTLC; + else + htlc->state = RCVD_ADD_HTLC; + htlc->id = id; + htlc->msatoshi = msatoshi; + if (!blocks_to_abs_locktime(expiry, &htlc->expiry)) + return CHANNEL_ERR_INVALID_EXPIRY; + htlc->rhash = *payment_hash; + htlc->r = NULL; + + /* BOLT #2: + * + * 1. type: 128 (`update_add_htlc`) + * 2. data: + * * [8:channel-id] + * * [8:id] + * * [4:amount-msat] + * * [4:cltv-expiry] + * * [32:payment-hash] + * * [1254:onion-routing-packet] + */ + htlc->routing = tal_dup_arr(htlc, u8, routing, 1254, 0); + + /* FIXME: check expiry etc. against config. */ + /* FIXME: set deadline */ + + old = htlc_get(&channel->htlcs, htlc->id, htlc_owner(htlc)); + if (old) { + if (old->state != htlc->state + || old->msatoshi != htlc->msatoshi + || old->expiry.locktime != htlc->expiry.locktime + || !structeq(&old->rhash, &htlc->rhash)) + e = CHANNEL_ERR_DUPLICATE_ID_DIFFERENT; + else + e = CHANNEL_ERR_DUPLICATE; + goto out; + } + + /* We're always considering the recipient's view of the channel here */ + view = &channel->view[recipient]; + + /* BOLT #2: + * + * A receiving node SHOULD fail the channel if it receives an + * `amount-sat` equal to zero, below its own `htlc-minimum-msat`, + * or... + */ + if (htlc->msatoshi == 0) { + e = CHANNEL_ERR_HTLC_BELOW_MINIMUM; + goto out; + } + if (htlc->msatoshi < htlc_minimum_msat(channel, recipient)) { + e = CHANNEL_ERR_HTLC_BELOW_MINIMUM; + goto out; + } + + /* Figure out what receiver will already be committed to. */ + gather_htlcs(tmpctx, channel, recipient, &committed, &removing, &adding); + htlc_arr_append(&adding, htlc); + + /* BOLT #2: + * + * A receiving node SHOULD fail the channel if a sending node + * adds more than its `max-accepted-htlcs` HTLCs to its local + * commitment transaction */ + if (tal_count(committed) - tal_count(removing) + tal_count(adding) + > max_accepted_htlcs(channel, recipient)) { + e = CHANNEL_ERR_TOO_MANY_HTLCS; + goto out; + } + + msat_in_htlcs = total_offered_msatoshis(committed, htlc_owner(htlc)) + - total_offered_msatoshis(removing, htlc_owner(htlc)) + + total_offered_msatoshis(adding, htlc_owner(htlc)); + + /* BOLT #2: + * + * A receiving node SHOULD fail the channel if a sending node + * adds more than `max-htlc-value-in-flight-msat` in HTLCs to + * its local commitment transaction. */ + if (msat_in_htlcs > max_htlc_value_in_flight_msat(channel, recipient)) { + e = CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; + goto out; + } + + /* BOLT #2: + * + * or which the sending node cannot afford at the current `fee-rate` + * while maintaining its channel reserve. + */ + if (channel->funder == htlc_owner(htlc)) { + u64 feerate = view->feerate_per_kw; + u64 dust = dust_limit_satoshis(channel, recipient); + size_t untrimmed; + + assert(feerate >= 1); + assert(dust >= 1); + untrimmed = commit_tx_num_untrimmed(committed, feerate, dust, + recipient) + + commit_tx_num_untrimmed(adding, feerate, dust, + recipient) + - commit_tx_num_untrimmed(removing, feerate, dust, + recipient); + + fee_msat = commit_tx_base_fee(feerate, untrimmed); + } else + fee_msat = 0; + + assert(fee_msat >= 0); + + /* Figure out what balance sender would have after applying all + * pending changes. */ + balance_msat = view->owed_msat[sender]; + + assert(balance_msat >= 0); + for (i = 0; i < tal_count(removing); i++) + balance_msat += balance_removing_htlc(removing[i], sender); + assert(balance_msat >= 0); + for (i = 0; i < tal_count(adding); i++) + balance_msat += balance_adding_htlc(adding[i], sender); + assert(balance_msat >= 0); + + /* This is a little subtle: + * + * The change is being applied to the receiver but it will + * come back to the sender after revoke_and_ack. So the check + * here is that the balance to the sender doesn't go below the + * sender's reserve. */ + if (balance_msat - fee_msat < (s64)channel_reserve_msat(channel, sender)) { + e = CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + goto out; + } + + htlc_map_add(&channel->htlcs, tal_steal(channel, htlc)); + e = CHANNEL_ERR_ADD_OK; + +out: + tal_free(tmpctx); + return e; +} + +struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id) +{ + return htlc_get(&channel->htlcs, id, sender); +} + +enum channel_remove_err channel_fulfill_htlc(struct channel *channel, + enum side sender, + u64 id, + const struct preimage *preimage) +{ + struct sha256 hash; + struct htlc *htlc; + + /* Fulfill is done by !creator of HTLC */ + htlc = channel_get_htlc(channel, !sender, id); + if (!htlc) + return CHANNEL_ERR_NO_SUCH_ID; + + if (htlc->r) + return CHANNEL_ERR_ALREADY_FULFILLED; + + sha256(&hash, preimage, sizeof(*preimage)); + /* BOLT #2: + * + * A receiving node MUST check that the `payment-preimage` value in + * `update-fulfill_htlc` SHA256 hashes to the corresponding HTLC + * `payment-hash`, and MUST fail the channel if it does not. + */ + if (!structeq(&hash, &htlc->rhash)) + return CHANNEL_ERR_BAD_PREIMAGE; + + htlc->r = tal_dup(htlc, struct preimage, preimage); + + /* BOLT #2: + * + * A receiving node MUST check that `id` corresponds to an HTLC in its + * current commitment transaction, and MUST fail the channel if it + * does not. + */ + if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { + status_trace("channel_fulfill_htlc: %"PRIu64" in state %s", + htlc->id, htlc_state_name(htlc->state)); + return CHANNEL_ERR_HTLC_UNCOMMITTED; + } + + /* We enforce a stricter check, forcing state machine to be linear, + * based on: */ + /* BOLT #2: + * + * A node MUST NOT send `update_fulfill_htlc` until an HTLC is + * irrevocably committed in both sides' commitment transactions. + */ + if (htlc->state == SENT_ADD_ACK_REVOCATION) + htlc->state = RCVD_REMOVE_HTLC; + else if (htlc->state == RCVD_ADD_ACK_REVOCATION) + htlc->state = SENT_REMOVE_HTLC; + else { + status_trace("channel_fulfill_htlc: %"PRIu64" in state %s", + htlc->id, htlc_state_name(htlc->state)); + return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; + } + + return CHANNEL_ERR_REMOVE_OK; +} + +static void htlc_incstate(struct channel *channel, + struct htlc *htlc, + enum side sidechanged) +{ + int preflags, postflags; + const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); + + status_trace("htlc %"PRIu64": %s->%s", htlc->id, + htlc_state_name(htlc->state), + htlc_state_name(htlc->state+1)); + + preflags = htlc_state_flags(htlc->state); + postflags = htlc_state_flags(htlc->state + 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))); + + htlc->state++; + + /* If we've added or removed, adjust balances. */ + if (!(preflags & committed_f) && (postflags & committed_f)) { + status_trace("htlc added %s: local %+"PRIi64" remote %+"PRIi64, + side_to_str(sidechanged), + balance_adding_htlc(htlc, LOCAL), + balance_adding_htlc(htlc, REMOTE)); + channel->view[sidechanged].owed_msat[LOCAL] + += balance_adding_htlc(htlc, LOCAL); + channel->view[sidechanged].owed_msat[REMOTE] + += balance_adding_htlc(htlc, REMOTE); + } else if ((preflags & committed_f) && !(postflags & committed_f)) { + status_trace("htlc removed %s: local %+"PRIi64" remote %+"PRIi64, + side_to_str(sidechanged), + balance_removing_htlc(htlc, LOCAL), + balance_removing_htlc(htlc, REMOTE)); + channel->view[sidechanged].owed_msat[LOCAL] + += balance_removing_htlc(htlc, LOCAL); + channel->view[sidechanged].owed_msat[REMOTE] + += balance_removing_htlc(htlc, REMOTE); + } +} + +/* FIXME: Commit to storage when this happens. */ +static bool change_htlcs(struct channel *channel, + enum side sidechanged, + const enum htlc_state *htlc_states, + size_t n_hstates) +{ + struct htlc_map_iter it; + struct htlc *h; + bool changed = false; + size_t i; + + for (h = htlc_map_first(&channel->htlcs, &it); + h; + h = htlc_map_next(&channel->htlcs, &it)) { + for (i = 0; i < n_hstates; i++) { + if (h->state == htlc_states[i]) { + htlc_incstate(channel, h, sidechanged); + changed = true; + } + } + } + return changed; +} + +/* FIXME: Handle fee changes too. */ +bool channel_sent_commit(struct channel *channel) +{ + const enum htlc_state states[] = { SENT_ADD_HTLC, + SENT_REMOVE_REVOCATION, + SENT_ADD_REVOCATION, + SENT_REMOVE_HTLC }; + status_trace("sent commit"); + return change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states)); +} + +bool channel_rcvd_revoke_and_ack(struct channel *channel) +{ + const enum htlc_state states[] = { SENT_ADD_COMMIT, + SENT_REMOVE_ACK_COMMIT, + SENT_ADD_ACK_COMMIT, + SENT_REMOVE_COMMIT }; + + status_trace("received revoke_and_ack"); + return change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states)); +} + +/* FIXME: We can actually merge these two... */ +bool channel_rcvd_commit(struct channel *channel) +{ + const enum htlc_state states[] = { RCVD_ADD_REVOCATION, + RCVD_REMOVE_HTLC, + RCVD_ADD_HTLC, + RCVD_REMOVE_REVOCATION }; + + status_trace("received commit"); + return change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states)); +} + +bool channel_sent_revoke_and_ack(struct channel *channel) +{ + const enum htlc_state states[] = { RCVD_ADD_ACK_COMMIT, + RCVD_REMOVE_COMMIT, + RCVD_ADD_COMMIT, + RCVD_REMOVE_ACK_COMMIT }; + status_trace("sent revoke_and_ack"); + return change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states)); +} + +static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view) +{ + return tal_fmt(ctx, "{ feerate_per_kw=%"PRIu64"," + " owed_local=%"PRIu64"," + " owed_remote=%"PRIu64" }", + view->feerate_per_kw, + view->owed_msat[LOCAL], + view->owed_msat[REMOTE]); +} + +static char *fmt_channel(const tal_t *ctx, const struct channel *channel) +{ + return tal_fmt(ctx, "{ funding_msat=%"PRIu64"," + " funder=%s," + " local=%s," + " remote=%s }", + channel->funding_msat, + side_to_str(channel->funder), + fmt_channel_view(ctx, &channel->view[LOCAL]), + fmt_channel_view(ctx, &channel->view[REMOTE])); +} +REGISTER_TYPE_TO_STRING(channel, fmt_channel); diff --git a/lightningd/channel.h b/lightningd/channel.h new file mode 100644 index 000000000..2f350841f --- /dev/null +++ b/lightningd/channel.h @@ -0,0 +1,353 @@ +#ifndef LIGHTNING_LIGHTNINGD_CHANNEL_H +#define LIGHTNING_LIGHTNINGD_CHANNEL_H +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +struct signature; + +/* View from each side */ +struct channel_view { + /* Current feerate in satoshis per 1000 weight. */ + u64 feerate_per_kw; + + /* What commitment number are we up to */ + u64 commitment_number; + + /* How much is owed to each side (includes pending changes) */ + u64 owed_msat[NUM_SIDES]; +}; + +struct channel { + /* Funding txid and output. */ + struct sha256_double funding_txid; + unsigned int funding_txout; + + /* Millisatoshis in from commitment tx */ + u64 funding_msat; + + /* Who is paying fees. */ + enum side funder; + + /* Limits and settings on this channel. */ + const struct channel_config *config[NUM_SIDES]; + + /* Basepoints for deriving keys. */ + struct pubkey revocation_basepoint[NUM_SIDES]; + struct pubkey payment_basepoint[NUM_SIDES]; + struct pubkey delayed_payment_basepoint[NUM_SIDES]; + + /* Mask for obscuring the encoding of the commitment number. */ + u64 commitment_number_obscurer; + + /* All live HTLCs for this channel */ + struct htlc_map htlcs; + + /* What it looks like to each side. */ + struct channel_view view[NUM_SIDES]; +}; + +/* Some requirements are self-specified (eg. my dust limit), others + * are force upon the other side (eg. minimum htlc you can add). + * + * These values are also universally in msatsoshi. These avoid + * confusion: use them! */ + +/* BOLT #2: + * + * `dust-limit-satoshis` is the threshold below which output should be + * generated for this node's commitment or HTLC transaction */ +static inline u64 dust_limit_satoshis(const struct channel *channel, + enum side side) +{ + return channel->config[side]->dust_limit_satoshis; +} +/* BOLT #2: + * + * `max-htlc-value-in-inflight-msat` is a cap on total value of + * outstanding HTLCs, which allows a node to limit its exposure to + * HTLCs */ +static inline u64 max_htlc_value_in_flight_msat(const struct channel *channel, + enum side recipient) +{ + return channel->config[recipient]->max_htlc_value_in_flight_msat; +} +/* BOLT #2: + * + * similarly `max-accepted-htlcs` limits the number of outstanding + * HTLCs the other node can offer. */ +static inline u16 max_accepted_htlcs(const struct channel *channel, + enum side recipient) +{ + return channel->config[recipient]->max_accepted_htlcs; +} +/* BOLT #2: + * + * `channel-reserve-satoshis` is the minimum amount that the other + * node is to keep as a direct payment. */ +static inline u64 channel_reserve_msat(const struct channel *channel, + enum side side) +{ + return channel->config[!side]->channel_reserve_satoshis * 1000; +} +/* BOLT #2: + * + * `htlc-minimum-msat` indicates the smallest value HTLC this node will accept. + */ +static inline u32 htlc_minimum_msat(const struct channel *channel, + enum side recipient) +{ + return channel->config[recipient]->htlc_minimum_msat; +} +/* BOLT #2: + * + * `to-self-delay` is the number of blocks that the other nodes + * to-self outputs must be delayed, using `OP_CHECKSEQUENCEVERIFY` + * delays */ +static inline u16 to_self_delay(const struct channel *channel, enum side side) +{ + return channel->config[!side]->to_self_delay; +} + + +/** + * new_channel: Given initial fees and funding, what is initial state? + * @ctx: tal context to allocate return value from. + * @funding_txid: The commitment transaction id. + * @funding_txout: The commitment transaction output number. + * @funding_satoshis: The commitment transaction amount. + * @funding_satoshis: The commitment transaction amount. + * @push_msat: The amount the initator gives to the other side. + * @feerate_per_kw: feerate per kiloweight (satoshis) + * @local: local channel configuration + * @remote: remote channel configuration + * @local_revocation_basepoint: local basepoint for revocations. + * @remote_revocation_basepoint: remote basepoint for revocations. + * @local_payment_basepoint: local basepoint for payments. + * @remote_payment_basepoint: remote basepoint for payments. + * @local_delayed_payment_basepoint: local basepoint for delayed payments. + * @remote_delayed_payment_basepoint: remote basepoint for delayed payments. + * @funder: which side initiated it. + * + * Returns state, or NULL if malformed. + */ +struct channel *new_channel(const tal_t *ctx, + const struct sha256_double *funding_txid, + unsigned int funding_txout, + u64 funding_satoshis, + u64 push_msat, + u32 feerate_per_kw, + const struct channel_config *local, + const struct channel_config *remote, + const struct pubkey *local_revocation_basepoint, + const struct pubkey *remote_revocation_basepoint, + const struct pubkey *local_payment_basepoint, + const struct pubkey *remote_payment_basepoint, + const struct pubkey *local_delayed_payment_basepoint, + const struct pubkey *remote_delayed_payment_basepoint, + enum side funder); +/** + * channel_tx: Get the current commitment transaction for the channel. + * @ctx: tal context to allocate return value from. + * @channel: The channel to evaluate + * @per_commitment_point: Per-commitment point to determine keys + * @htlc_map: Pointer to htlcs for each tx output (allocated off @ctx) or NULL. + * @side: which side to get the commitment transaction for + * + * Returns the unsigned commitment transaction for the committed state + * for @side and fills in @htlc_map (if not NULL), or NULL on key + * derivation failure. + */ +struct bitcoin_tx *channel_tx(const tal_t *ctx, + const struct channel *channel, + const struct pubkey *per_commitment_point, + const struct htlc ***htlcmap, + enum side side); + +/** + * actual_feerate: what is the actual feerate for the local side. + * @channel: The channel state + * @theirsig: The other side's signature + * + * The fee calculated on a commitment transaction is a worst-case + * approximation. It's also possible that the desired feerate is not + * met, because the initiator sets it while the other side is adding many + * htlcs. + * + * This is the fee rate we actually care about, if we're going to check + * whether it's actually too low. + */ +uint32_t actual_feerate(const struct channel *channel, + const struct signature *theirsig); + +/** + * copy_channel: Make a deep copy of channel + * @ctx: tal context to allocate return value from. + * @channel: channel to copy. + */ +struct channel *copy_channel(const tal_t *ctx, const struct channel *channel); + +enum channel_add_err { + /* All OK! */ + CHANNEL_ERR_ADD_OK, + /* Bad expiry value */ + CHANNEL_ERR_INVALID_EXPIRY, + /* Not really a failure, if expected: it's an exact duplicate. */ + CHANNEL_ERR_DUPLICATE, + /* Same ID, but otherwise different. */ + CHANNEL_ERR_DUPLICATE_ID_DIFFERENT, + /* Would exceed the specified max_htlc_value_in_flight_msat */ + CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED, + /* Can't afford it */ + CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED, + /* HTLC is below htlc_minimum_msat */ + CHANNEL_ERR_HTLC_BELOW_MINIMUM, + /* HTLC would push past max_accepted_htlcs */ + CHANNEL_ERR_TOO_MANY_HTLCS, +}; + +/** + * channel_add_htlc: append an HTLC to channel if it can afford it + * @channel: The channel + * @offerer: the side offering the HTLC (to the other side). + * @id: unique HTLC id. + * @msatoshi: amount in millisatoshi. + * @expiry: block number when HTLC can no longer be redeemed. + * @payment_hash: hash whose preimage can redeem HTLC. + * @routing: routing information (copied) + * + * If this returns CHANNEL_ERR_NONE, the fee htlc was added and + * the output amounts adjusted accordingly. Otherwise nothing + * is changed. + */ +enum channel_add_err channel_add_htlc(struct channel *channel, + enum side sender, + u64 id, + u64 msatoshi, + u32 expiry, + const struct sha256 *payment_hash, + const u8 routing[1254]); + +/** + * channel_get_htlc: find an HTLC + * @channel: The channel + * @offerer: the side offering the HTLC. + * @id: unique HTLC id. + */ +struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id); + +enum channel_remove_err { + /* All OK! */ + CHANNEL_ERR_REMOVE_OK, + /* No such HTLC. */ + CHANNEL_ERR_NO_SUCH_ID, + /* Already have fulfilled it */ + CHANNEL_ERR_ALREADY_FULFILLED, + /* Preimage doesn't hash to value. */ + CHANNEL_ERR_BAD_PREIMAGE, + /* HTLC is not committed */ + CHANNEL_ERR_HTLC_UNCOMMITTED, + /* HTLC is not committed and prior revoked on both sides */ + CHANNEL_ERR_HTLC_NOT_IRREVOCABLE +}; + +/** + * channel_fail_htlc: remove an HTLC, funds to the side which offered it. + * @channel: The channel state + * @sender: the side fulfilling the HTLC (opposite to side which sent it) + * @id: unique HTLC id. + * + * This will remove the htlc and credit the value of the HTLC (back) + * to its offerer. + */ +enum channel_remove_err channel_fail_htlc(struct channel *channel, + enum side sender, u64 id); + +/** + * channel_fulfill_htlc: remove an HTLC, funds to side which accepted it. + * @channel: The channel state + * @sender: the side fulfilling the HTLC (opposite to side which sent it) + * @id: unique HTLC id. + * + * If the htlc exists, is not already fulfilled, the preimage is correct and + * HTLC committed at the recipient, this will add a pending change to + * remove the htlc and give the value of the HTLC to its recipient, + * and return CHANNEL_ERR_FULFILL_OK. Otherwise, it will return another error. + */ +enum channel_remove_err channel_fulfill_htlc(struct channel *channel, + enum side sender, + u64 id, + const struct preimage *preimage); + +/** + * approx_max_feerate: what's the we (initiator) could raise fee rate to? + * @channel: The channel state + * + * This is not exact! To check if their offer is valid, use can_afford_feerate. + */ +u64 approx_max_feerate(const struct channel *channel); + +/** + * can_afford_feerate: could the initiator pay for the fee at fee_rate? + * @channel: The channel state + * @feerate_per_kw: the new fee rate proposed + */ +bool can_afford_feerate(const struct channel *channel, u64 feerate_per_kw); + +/** + * adjust_fee: Change fee rate. + * @channel: The channel state + * @feerate_per_kw: fee in satoshi per 1000 bytes. + * @side: which side to adjust. + */ +void adjust_fee(struct channel *channel, u64 feerate_per_kw, enum side side); + +/** + * force_fee: Change fees to a specific value. + * @channel: The channel state + * @fee: fee in satoshi. + * + * This is used for the close transaction, which specifies an exact fee. + * If the fee cannot be paid in full, this return false (but cstate will + * still be altered). + */ +bool force_fee(struct channel *channel, u64 fee); + +/** + * channel_sent_commit: commit all remote outstanding changes. + * @channel: the channel + * + * This is where we commit to pending changes we've added; returns true if + * anything changed. */ +bool channel_sent_commit(struct channel *channel); + +/** + * channel_rcvd_revoke_and_ack: accept ack on remote committed changes. + * @channel: the channel + * + * This is where we commit to pending changes we've added; returns true if + * anything changed. */ +bool channel_rcvd_revoke_and_ack(struct channel *channel); + +/** + * channel_rcvd_commit: commit all local outstanding changes. + * @channel: the channel + * + * This is where we commit to pending changes we've added; returns true if + * anything changed. */ +bool channel_rcvd_commit(struct channel *channel); + +/** + * channel_sent_revoke_and_ack: sent ack on local committed changes. + * @channel: the channel + * + * This is where we commit to pending changes we've added; returns true if + * anything changed. */ +bool channel_sent_revoke_and_ack(struct channel *channel); + +#endif /* LIGHTNING_DAEMON_CHANNEL_H */ diff --git a/lightningd/test/run-channel.c b/lightningd/test/run-channel.c new file mode 100644 index 000000000..48c020fa3 --- /dev/null +++ b/lightningd/test/run-channel.c @@ -0,0 +1,501 @@ + #include + #include +#define status_trace(fmt , ...) \ + printf(fmt "\n" , ## __VA_ARGS__) + +#include "../key_derive.c" +#include "../channel.c" +#include "../commit_tx.c" +#include "../htlc_tx.c" +#include +#include +#include +#include +#include +#include + +static struct sha256 sha256_from_hex(const char *hex) +{ + struct sha256 sha256; + if (strstarts(hex, "0x")) + hex += 2; + if (!hex_decode(hex, strlen(hex), &sha256, sizeof(sha256))) + abort(); + return sha256; +} + +/* bitcoind loves its backwards txids! */ +static struct sha256_double txid_from_hex(const char *hex) +{ + struct sha256_double sha256; + struct sha256 rev = sha256_from_hex(hex); + size_t i; + + for (i = 0; i < sizeof(rev); i++) + sha256.sha.u.u8[sizeof(sha256) - 1 - i] = rev.u.u8[i]; + return sha256; +} + +/* BOLT #3: + * + * local_feerate_per_kw: 0 + * ... + * local_feerate_per_kw: 678 + * ... + * local_feerate_per_kw: 679 + * ... + * local_feerate_per_kw: 2168 + * ... + * local_feerate_per_kw: 2169 + * ... + * local_feerate_per_kw: 2294 + * ... + * local_feerate_per_kw: 2295 + * ... + * local_feerate_per_kw: 3872 + * ... + * local_feerate_per_kw: 3873 + * ... + * local_feerate_per_kw: 5149 + * ... + * local_feerate_per_kw: 5150 + * ... + * local_feerate_per_kw: 9651180 + * ... + * local_feerate_per_kw: 9651181 + * ... + * local_feerate_per_kw: 9651936 + */ +static u64 feerates[] = { + 0, + 678, + 679, + 2168, + 2169, + 2294, + 2295, + 3872, + 3873, + 5149, + 5150, + 9651180, + 9651181, + 9651936 +}; + +/* BOLT #3: + * + * htlc 0 direction: remote->local + * htlc 0 amount_msat: 1000000 + * htlc 0 expiry: 500 + * htlc 0 payment_preimage: 0000000000000000000000000000000000000000000000000000000000000000 + * htlc 1 direction: remote->local + * htlc 1 amount_msat: 2000000 + * htlc 1 expiry: 501 + * htlc 1 payment_preimage: 0101010101010101010101010101010101010101010101010101010101010101 + * htlc 2 direction: local->remote + * htlc 2 amount_msat: 2000000 + * htlc 2 expiry: 502 + * htlc 2 payment_preimage: 0202020202020202020202020202020202020202020202020202020202020202 + * htlc 3 direction: local->remote + * htlc 3 amount_msat: 3000000 + * htlc 3 expiry: 503 + * htlc 3 payment_preimage: 0303030303030303030303030303030303030303030303030303030303030303 + * htlc 4 direction: remote->local + * htlc 4 amount_msat: 4000000 + * htlc 4 expiry: 504 + * htlc 4 payment_preimage: 0404040404040404040404040404040404040404040404040404040404040404 + */ +static const struct htlc **add_htlcs(struct channel *channel, enum side side) +{ + int i; + const struct htlc **htlcs = tal_arr(channel, const struct htlc *, 5); + u8 *dummy_routing = tal_arr(htlcs, u8, 1254); + + for (i = 0; i < 5; i++) { + struct preimage preimage; + struct sha256 hash; + enum channel_add_err e; + enum side sender; + u64 msatoshi; + + switch (i) { + case 0: + sender = !side; + msatoshi = 1000000; + break; + case 1: + sender = !side; + msatoshi = 2000000; + break; + case 2: + sender = side; + msatoshi = 2000000; + break; + case 3: + sender = side; + msatoshi = 3000000; + break; + case 4: + sender = !side; + msatoshi = 4000000; + break; + } + memset(&preimage, i, sizeof(preimage)); + sha256(&hash, &preimage, sizeof(preimage)); + e = channel_add_htlc(channel, sender, i, msatoshi, 500+i, &hash, + dummy_routing); + assert(e == CHANNEL_ERR_ADD_OK); + htlcs[i] = channel_get_htlc(channel, sender, i); + } + tal_free(dummy_routing); + + /* Now make HTLCs fully committed. */ + channel_sent_commit(channel); + channel_rcvd_revoke_and_ack(channel); + channel_rcvd_commit(channel); + channel_sent_revoke_and_ack(channel); + channel_sent_commit(channel); + channel_rcvd_revoke_and_ack(channel); + return htlcs; +} + +static struct pubkey pubkey_from_hex(const char *hex) +{ + struct pubkey pubkey; + + if (strstarts(hex, "0x")) + hex += 2; + if (!pubkey_from_hexstr(hex, strlen(hex), &pubkey)) + abort(); + return pubkey; +} + +static void tx_must_be_eq(const struct bitcoin_tx *a, + const struct bitcoin_tx *b) +{ + tal_t *tmpctx = tal_tmpctx(NULL); + u8 *lina, *linb; + size_t i, len; + + lina = linearize_tx(tmpctx, a); + linb = linearize_tx(tmpctx, b); + + len = tal_len(lina); + if (tal_len(linb) < len) + len = tal_len(linb); + + for (i = 0; i < tal_len(lina); i++) { + if (i >= tal_len(linb)) + errx(1, "Second tx is truncated:\n" + "%s\n" + "%s", + tal_hex(tmpctx, lina), + tal_hex(tmpctx, linb)); + if (lina[i] != linb[i]) + errx(1, "tx differ at offset %zu:\n" + "%s\n" + "%s", + i, + tal_hex(tmpctx, lina), + tal_hex(tmpctx, linb)); + } + if (i != tal_len(linb)) + errx(1, "First tx is truncated:\n" + "%s\n" + "%s", + tal_hex(tmpctx, lina), + tal_hex(tmpctx, linb)); + tal_free(tmpctx); +} + +static void send_and_fulfill_htlc(struct channel *channel, + enum side sender, + u64 msatoshi) +{ + struct preimage r; + struct sha256 rhash; + u8 *dummy_routing = tal_arr(channel, u8, 1254); + + memset(&r, 0, sizeof(r)); + sha256(&rhash, &r, sizeof(r)); + + assert(channel_add_htlc(channel, sender, 1337, msatoshi, 900, &rhash, + dummy_routing) == CHANNEL_ERR_ADD_OK); + + if (sender == LOCAL) { + /* Step through a complete cycle. */ + channel_sent_commit(channel); + channel_rcvd_revoke_and_ack(channel); + channel_rcvd_commit(channel); + channel_sent_revoke_and_ack(channel); + assert(channel_fulfill_htlc(channel, REMOTE, 1337, &r) + == CHANNEL_ERR_REMOVE_OK); + channel_rcvd_commit(channel); + channel_sent_revoke_and_ack(channel); + channel_sent_commit(channel); + channel_rcvd_revoke_and_ack(channel); + assert(channel_get_htlc(channel, sender, 1337)->state + == RCVD_REMOVE_ACK_REVOCATION); + } else { + channel_rcvd_commit(channel); + channel_sent_revoke_and_ack(channel); + channel_sent_commit(channel); + channel_rcvd_revoke_and_ack(channel); + assert(channel_fulfill_htlc(channel, LOCAL, 1337, &r) + == CHANNEL_ERR_REMOVE_OK); + channel_sent_commit(channel); + channel_rcvd_revoke_and_ack(channel); + channel_rcvd_commit(channel); + channel_sent_revoke_and_ack(channel); + assert(channel_get_htlc(channel, sender, 1337)->state + == SENT_REMOVE_ACK_REVOCATION); + } +} + +int main(void) +{ + tal_t *tmpctx = tal_tmpctx(NULL); + struct sha256_double funding_txid; + /* We test from both sides. */ + struct channel *lchannel, *rchannel; + u64 funding_amount_satoshi, feerate_per_kw; + unsigned int funding_output_index; + struct pubkey localkey, remotekey; + struct pubkey local_delayedkey; + struct pubkey local_revocation_key; + struct pubkey local_revocation_basepoint, local_delayed_payment_basepoint, + local_payment_basepoint, remote_payment_basepoint, + local_per_commitment_point; + struct pubkey *unknown = tal(tmpctx, struct pubkey); + struct bitcoin_tx *raw_tx, *tx; + struct channel_config *local_config = tal(tmpctx, struct channel_config); + struct channel_config *remote_config = tal(tmpctx, struct channel_config); + u64 to_local_msat, to_remote_msat; + const struct htlc **htlc_map, **htlcs; + size_t i; + + secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY + | SECP256K1_CONTEXT_SIGN); + + /* BOLT #3: + * + * # Appendix C: Commitment and HTLC Transaction Test Vectors + * + * In the following: + * - we consider *local* transactions, which implies that all payments + * to *local* are delayed + * - we assume that *local* is the funder + * - private keys are displayed as 32 bytes plus a trailing 1 + * (bitcoin's convention for "compressed" private keys, i.e. keys + * for which the public key is compressed) + * + * - transaction signatures are all deterministic, using + * RFC6979 (using HMAC-SHA256) + * + * We start by defining common basic parameters for each test vector: + * the HTLCs are not used for the first "simple commitment tx with no + * HTLCs" test. + * + * funding_tx_id: 8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be + * funding_output_index: 0 + * funding_amount_satoshi: 10000000 + *... + * local_delay: 144 + * local_dust_limit_satoshi: 546 + */ + funding_txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); + funding_output_index = 0; + funding_amount_satoshi = 10000000; + + remote_config->to_self_delay = 144; + local_config->dust_limit_satoshis = 546; + /* This matters only because we check if added HTLC will create new + * output, for fee considerations. */ + remote_config->dust_limit_satoshis = 546; + + local_config->max_htlc_value_in_flight_msat = -1ULL; + remote_config->max_htlc_value_in_flight_msat = -1ULL; + local_config->channel_reserve_satoshis = 0; + remote_config->channel_reserve_satoshis = 0; + local_config->htlc_minimum_msat = 0; + remote_config->htlc_minimum_msat = 0; + local_config->max_accepted_htlcs = 0xFFFF; + remote_config->max_accepted_htlcs = 0xFFFF; + + /* BOLT #3: + * + * # From local_revocation_basepoint_secret + * INTERNAL: local_revocation_basepoint: 02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27 + * # From local_delayed_payment_basepoint_secret + * INTERNAL: local_delayed_payment_basepoint: 023c72addb4fdf09af94f0c94d7fe92a386a7e70cf8a1d85916386bb2535c7b1b1 + */ + local_revocation_basepoint = pubkey_from_hex("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27"); + local_delayed_payment_basepoint = pubkey_from_hex("023c72addb4fdf09af94f0c94d7fe92a386a7e70cf8a1d85916386bb2535c7b1b1"); + + /* BOLT #3: + * + * local_payment_basepoint: 034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa + * remote_payment_basepoint: 032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991 + * # obscured commitment transaction number = 0x2bb038521914 ^ 42 + */ + local_payment_basepoint = pubkey_from_hex("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"); + remote_payment_basepoint = pubkey_from_hex("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991"); + + /* BOLT #3: + * + * name: simple commitment tx with no HTLCs + * to_local_msat: 7000000000 + * to_remote_msat: 3000000000 + * feerate_per_kw: 15000 + */ + + /* We put unknown in for some things; valgrind will warn if used. */ + to_local_msat = 7000000000; + to_remote_msat = 3000000000; + feerate_per_kw = 15000; + lchannel = new_channel(tmpctx, &funding_txid, funding_output_index, + funding_amount_satoshi, to_remote_msat, + feerate_per_kw, + local_config, + remote_config, + &local_revocation_basepoint, + unknown, + &local_payment_basepoint, + &remote_payment_basepoint, + &local_delayed_payment_basepoint, + unknown, + LOCAL); + + rchannel = new_channel(tmpctx, &funding_txid, funding_output_index, + funding_amount_satoshi, to_remote_msat, + feerate_per_kw, + remote_config, + local_config, + unknown, + &local_revocation_basepoint, + &remote_payment_basepoint, + &local_payment_basepoint, + unknown, + &local_delayed_payment_basepoint, + REMOTE); + /* BOLT #3: + * + * commitment_number: 42 + */ + lchannel->view[LOCAL].commitment_number + = rchannel->view[REMOTE].commitment_number = 42; + + /* BOLT #3: + * + * INTERNAL: local_per_commitment_point: 025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486 + */ + local_per_commitment_point = pubkey_from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486"); + /* BOLT #3: + * localkey: 030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7 + * remotekey: 0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b + * local_delayedkey: 03fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c + * local_revocation_key: 0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19 + */ + localkey = pubkey_from_hex("030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7"); + remotekey = pubkey_from_hex("0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b"); + local_delayedkey = pubkey_from_hex("03fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c"); + local_revocation_key = pubkey_from_hex("0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19"); + + raw_tx = commit_tx(tmpctx, &funding_txid, funding_output_index, + funding_amount_satoshi, + LOCAL, remote_config->to_self_delay, + &local_revocation_key, + &local_delayedkey, + &localkey, + &remotekey, + feerate_per_kw, + local_config->dust_limit_satoshis, + to_local_msat, + to_remote_msat, + NULL, &htlc_map, 0x2bb038521914 ^ 42, LOCAL); + + tx = channel_tx(tmpctx, lchannel, &local_per_commitment_point, + &htlc_map, LOCAL); + tx_must_be_eq(tx, raw_tx); + + tx = channel_tx(tmpctx, rchannel, &local_per_commitment_point, + &htlc_map, REMOTE); + tx_must_be_eq(tx, raw_tx); + + /* BOLT #3: + * + * name: commitment tx with all 5 htlcs untrimmed (minimum feerate) + * to_local_msat: 6988000000 + * to_remote_msat: 3000000000 + * local_feerate_per_kw: 0 + */ + to_local_msat = 6988000000; + to_remote_msat = 3000000000; + feerate_per_kw = 0; + + /* Now, BOLT doesn't adjust owed amounts the same way we do + * here: it's as if local side paid for all the HTLCs. We can + * fix this by having local side offer an HTLC, and having + * remote side accept it */ + send_and_fulfill_htlc(lchannel, LOCAL, 7000000); + send_and_fulfill_htlc(rchannel, REMOTE, 7000000); + + assert(lchannel->view[LOCAL].owed_msat[LOCAL] + == rchannel->view[REMOTE].owed_msat[REMOTE]); + assert(lchannel->view[REMOTE].owed_msat[REMOTE] + == rchannel->view[LOCAL].owed_msat[LOCAL]); + + raw_tx = channel_tx(tmpctx, lchannel, &local_per_commitment_point, + &htlc_map, LOCAL); + tx = channel_tx(tmpctx, rchannel, &local_per_commitment_point, + &htlc_map, REMOTE); + tx_must_be_eq(tx, raw_tx); + + /* FIXME: Adjust properly! */ + lchannel->view[LOCAL].feerate_per_kw = feerate_per_kw; + rchannel->view[REMOTE].feerate_per_kw = feerate_per_kw; + htlcs = add_htlcs(lchannel, LOCAL); + add_htlcs(rchannel, REMOTE); + + assert(lchannel->view[LOCAL].owed_msat[LOCAL] + == rchannel->view[REMOTE].owed_msat[REMOTE]); + assert(lchannel->view[REMOTE].owed_msat[REMOTE] + == rchannel->view[LOCAL].owed_msat[LOCAL]); + + for (i = 0; i < ARRAY_SIZE(feerates); i++) { + feerate_per_kw = feerates[i]; + + lchannel->view[LOCAL].feerate_per_kw = feerate_per_kw; + rchannel->view[REMOTE].feerate_per_kw = feerate_per_kw; + + raw_tx = commit_tx(tmpctx, &funding_txid, funding_output_index, + funding_amount_satoshi, + LOCAL, remote_config->to_self_delay, + &local_revocation_key, + &local_delayedkey, + &localkey, + &remotekey, + feerate_per_kw, + local_config->dust_limit_satoshis, + to_local_msat, + to_remote_msat, + htlcs, &htlc_map, + 0x2bb038521914 ^ 42, LOCAL); + + tx = channel_tx(tmpctx, lchannel, &local_per_commitment_point, + &htlc_map, LOCAL); + tx_must_be_eq(tx, raw_tx); + + tx = channel_tx(tmpctx, rchannel, &local_per_commitment_point, + &htlc_map, REMOTE); + tx_must_be_eq(tx, raw_tx); + } + + /* No memory leaks please */ + secp256k1_context_destroy(secp256k1_ctx); + tal_free(tmpctx); + + /* FIXME: Do BOLT comparison! */ + return 0; +} diff --git a/type_to_string.h b/type_to_string.h index a774161da..a96657544 100644 --- a/type_to_string.h +++ b/type_to_string.h @@ -22,6 +22,7 @@ union printable_types { const struct channel_id *channel_id; const struct privkey *privkey; const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature; + const struct channel *channel; const char *charp_; };