Browse Source
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>ppa-0.6.1
Rusty Russell
8 years ago
5 changed files with 1450 additions and 1 deletions
@ -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); |
@ -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 */ |
@ -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; |
|||
} |
Loading…
Reference in new issue