mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
channel: object to track channel state.
This object is basically the embodyment of BOLT #2. Each HTLC already knows its own state; this moves them between states and keeps them consistent. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -27,11 +27,13 @@ LIGHTNINGD_OLD_OBJS := $(LIGHTNINGD_OLD_SRC:.c=.o)
|
|||||||
LIGHTNINGD_OLD_HEADERS := $(LIGHTNINGD_OLD_SRC:.c=.h)
|
LIGHTNINGD_OLD_HEADERS := $(LIGHTNINGD_OLD_SRC:.c=.h)
|
||||||
|
|
||||||
LIGHTNINGD_OLD_LIB_SRC := \
|
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_OBJS := $(LIGHTNINGD_OLD_LIB_SRC:.c=.o)
|
||||||
LIGHTNINGD_OLD_LIB_HEADERS := $(LIGHTNINGD_OLD_LIB_SRC:.c=.h)
|
LIGHTNINGD_OLD_LIB_HEADERS := $(LIGHTNINGD_OLD_LIB_SRC:.c=.h)
|
||||||
|
|
||||||
LIGHTNINGD_LIB_SRC := \
|
LIGHTNINGD_LIB_SRC := \
|
||||||
|
lightningd/channel.c \
|
||||||
lightningd/channel_config.c \
|
lightningd/channel_config.c \
|
||||||
lightningd/commit_tx.c \
|
lightningd/commit_tx.c \
|
||||||
lightningd/cryptomsg.c \
|
lightningd/cryptomsg.c \
|
||||||
|
|||||||
592
lightningd/channel.c
Normal file
592
lightningd/channel.c
Normal file
@@ -0,0 +1,592 @@
|
|||||||
|
#include "channel.h"
|
||||||
|
#include "commit_tx.h"
|
||||||
|
#include "type_to_string.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <bitcoin/preimage.h>
|
||||||
|
#include <ccan/array_size/array_size.h>
|
||||||
|
#include <ccan/mem/mem.h>
|
||||||
|
#include <ccan/structeq/structeq.h>
|
||||||
|
#include <ccan/tal/str/str.h>
|
||||||
|
#include <daemon/htlc.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <lightningd/channel_config.h>
|
||||||
|
#include <lightningd/key_derive.h>
|
||||||
|
#include <status.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
353
lightningd/channel.h
Normal file
353
lightningd/channel.h
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
#ifndef LIGHTNING_LIGHTNINGD_CHANNEL_H
|
||||||
|
#define LIGHTNING_LIGHTNINGD_CHANNEL_H
|
||||||
|
#include "config.h"
|
||||||
|
#include <bitcoin/pubkey.h>
|
||||||
|
#include <bitcoin/shadouble.h>
|
||||||
|
#include <ccan/short_types/short_types.h>
|
||||||
|
#include <ccan/tal/tal.h>
|
||||||
|
#include <daemon/htlc.h>
|
||||||
|
#include <lightningd/channel_config.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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 */
|
||||||
501
lightningd/test/run-channel.c
Normal file
501
lightningd/test/run-channel.c
Normal file
@@ -0,0 +1,501 @@
|
|||||||
|
#include <status.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#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 <bitcoin/preimage.h>
|
||||||
|
#include <bitcoin/privkey.h>
|
||||||
|
#include <bitcoin/pubkey.h>
|
||||||
|
#include <ccan/err/err.h>
|
||||||
|
#include <ccan/str/hex/hex.h>
|
||||||
|
#include <type_to_string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ union printable_types {
|
|||||||
const struct channel_id *channel_id;
|
const struct channel_id *channel_id;
|
||||||
const struct privkey *privkey;
|
const struct privkey *privkey;
|
||||||
const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature;
|
const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature;
|
||||||
|
const struct channel *channel;
|
||||||
const char *charp_;
|
const char *charp_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user