mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 14:24:09 +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:
parent
ec4db39a8e
commit
4a7418e3db
5 changed files with 1450 additions and 1 deletions
|
@ -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 \
|
||||
|
|
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 privkey *privkey;
|
||||
const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature;
|
||||
const struct channel *channel;
|
||||
const char *charp_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue