daemon: use htlc pointers everywhere.

No more copies!

I tried changing the cstate->side[].htlcs to htlc_map rather than a
simple pointer array, but we rely on those array indices heavily for
permutation mapping, and it turned into a major rewrite (especially
for the steal case).

Eventually, we're going to want to reconstruct the commit info for
older commit txs rather than keeping all the permutation and
per-commit-info HTLC information in memory, so we can do the work
then.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2016-06-30 09:08:11 +09:30
parent 67ac2d2081
commit cc4fc4b668
7 changed files with 240 additions and 251 deletions

View File

@@ -11,7 +11,7 @@
#include <assert.h> #include <assert.h>
static bool add_htlc(struct bitcoin_tx *tx, size_t n, static bool add_htlc(struct bitcoin_tx *tx, size_t n,
const struct channel_htlc *h, const struct htlc *h,
const struct pubkey *ourkey, const struct pubkey *ourkey,
const struct pubkey *theirkey, const struct pubkey *theirkey,
const struct sha256 *rhash, const struct sha256 *rhash,
@@ -96,7 +96,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
/* HTLCs this side sent. */ /* HTLCs this side sent. */
for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) { for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) {
if (!add_htlc(tx, num, &cstate->side[side].htlcs[i], if (!add_htlc(tx, num, cstate->side[side].htlcs[i],
self, other, rhash, locktime, self, other, rhash, locktime,
bitcoin_redeem_htlc_send)) bitcoin_redeem_htlc_send))
return tal_free(tx); return tal_free(tx);
@@ -104,7 +104,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
} }
/* HTLCs this side has received. */ /* HTLCs this side has received. */
for (i = 0; i < tal_count(cstate->side[!side].htlcs); i++) { for (i = 0; i < tal_count(cstate->side[!side].htlcs); i++) {
if (!add_htlc(tx, num, &cstate->side[!side].htlcs[i], if (!add_htlc(tx, num, cstate->side[!side].htlcs[i],
self, other, rhash, locktime, self, other, rhash, locktime,
bitcoin_redeem_htlc_recv)) bitcoin_redeem_htlc_recv))
return tal_free(tx); return tal_free(tx);

View File

@@ -36,13 +36,13 @@ static uint64_t calculate_fee_msat(size_t num_nondust_htlcs,
} }
/* Total, in millisatoshi. */ /* Total, in millisatoshi. */
static uint64_t htlcs_total(const struct channel_htlc *htlcs) static uint64_t htlcs_total(struct htlc **htlcs)
{ {
size_t i, n = tal_count(htlcs); size_t i, n = tal_count(htlcs);
uint64_t total = 0; uint64_t total = 0;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
total += htlcs[i].msatoshis; total += htlcs[i]->msatoshis;
return total; return total;
} }
@@ -152,8 +152,8 @@ struct channel_state *initial_cstate(const tal_t *ctx,
fundee = &cstate->side[!funding]; fundee = &cstate->side[!funding];
/* Neither side has HTLCs. */ /* Neither side has HTLCs. */
funder->htlcs = tal_arr(cstate, struct channel_htlc, 0); funder->htlcs = tal_arr(cstate, struct htlc *, 0);
fundee->htlcs = tal_arr(cstate, struct channel_htlc, 0); fundee->htlcs = tal_arr(cstate, struct htlc *, 0);
/* Initially, all goes back to funder. */ /* Initially, all goes back to funder. */
funder->pay_msat = anchor_satoshis * 1000 - fee_msat; funder->pay_msat = anchor_satoshis * 1000 - fee_msat;
@@ -174,12 +174,12 @@ bool is_dust_amount(uint64_t satoshis)
return satoshis < 546; return satoshis < 546;
} }
static size_t count_nondust_htlcs(const struct channel_htlc *htlcs) static size_t count_nondust_htlcs(struct htlc **htlcs)
{ {
size_t i, n = tal_count(htlcs), nondust = 0; size_t i, n = tal_count(htlcs), nondust = 0;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
if (!is_dust_amount(htlcs[i].msatoshis / 1000)) if (!is_dust_amount(htlcs[i]->msatoshis / 1000))
nondust++; nondust++;
return nondust; return nondust;
} }
@@ -211,14 +211,9 @@ bool force_fee(struct channel_state *cstate, uint64_t fee)
} }
/* Add a HTLC to @creator if it can afford it. */ /* Add a HTLC to @creator if it can afford it. */
struct channel_htlc *cstate_add_htlc(struct channel_state *cstate, bool cstate_add_htlc(struct channel_state *cstate,
u32 msatoshis, struct htlc *htlc,
const struct abs_locktime *expiry, enum channel_side side)
const struct sha256 *rhash,
uint64_t id,
const u8 *routing,
size_t routing_len,
enum channel_side side)
{ {
size_t n, nondust; size_t n, nondust;
struct channel_oneside *creator, *recipient; struct channel_oneside *creator, *recipient;
@@ -228,42 +223,32 @@ struct channel_htlc *cstate_add_htlc(struct channel_state *cstate,
/* Remember to count the new one in total txsize if not dust! */ /* Remember to count the new one in total txsize if not dust! */
nondust = total_nondust_htlcs(cstate); nondust = total_nondust_htlcs(cstate);
if (!is_dust_amount(msatoshis / 1000)) if (!is_dust_amount(htlc->msatoshis / 1000))
nondust++; nondust++;
if (!change_funding(cstate->anchor, cstate->fee_rate, if (!change_funding(cstate->anchor, cstate->fee_rate,
msatoshis, creator, recipient, nondust)) htlc->msatoshis, creator, recipient, nondust))
return NULL; return false;
n = tal_count(creator->htlcs); n = tal_count(creator->htlcs);
tal_resize(&creator->htlcs, n+1); tal_resize(&creator->htlcs, n+1);
creator->htlcs[n].msatoshis = msatoshis; creator->htlcs[n] = htlc;
creator->htlcs[n].expiry = *expiry; memcheck(&creator->htlcs[n]->msatoshis,
creator->htlcs[n].rhash = *rhash; sizeof(creator->htlcs[n]->msatoshis));
creator->htlcs[n].id = id; memcheck(&creator->htlcs[n]->rhash, sizeof(creator->htlcs[n]->rhash));
creator->htlcs[n].routing = tal_dup_arr(cstate, u8, routing,
routing_len, 0);
memcheck(&creator->htlcs[n].msatoshis,
sizeof(creator->htlcs[n].msatoshis));
memcheck(&creator->htlcs[n].rhash, sizeof(creator->htlcs[n].rhash));
cstate->changes++; cstate->changes++;
return &creator->htlcs[n]; return true;
} }
/* Remove htlc from creator, credit it to beneficiary. */ /* Remove htlc from creator, credit it to beneficiary. */
static void remove_htlc(struct channel_state *cstate, static void remove_htlc(struct channel_state *cstate,
enum channel_side creator, enum channel_side creator,
enum channel_side beneficiary, enum channel_side beneficiary,
struct channel_htlc *htlc) struct htlc *htlc)
{ {
size_t nondust; size_t nondust;
size_t n = tal_count(cstate->side[creator].htlcs); size_t i, n = tal_count(cstate->side[creator].htlcs);
const struct channel_htlc *end;
end = cstate->side[creator].htlcs + n;
assert(htlc >= cstate->side[creator].htlcs && htlc < end);
/* Remember to remove this one in total txsize if not dust! */ /* Remember to remove this one in total txsize if not dust! */
nondust = total_nondust_htlcs(cstate); nondust = total_nondust_htlcs(cstate);
@@ -280,69 +265,69 @@ static void remove_htlc(struct channel_state *cstate,
abort(); abort();
/* Actually remove the HTLC. */ /* Actually remove the HTLC. */
tal_free(htlc->routing); for (i = 0; i < tal_count(cstate->side[creator].htlcs); i++) {
memmove(htlc, htlc + 1, (end - htlc - 1) * sizeof(*htlc)); if (cstate->side[creator].htlcs[i] == htlc) {
tal_resize(&cstate->side[creator].htlcs, n-1); memmove(cstate->side[creator].htlcs + i,
cstate->changes++; cstate->side[creator].htlcs + i + 1,
(n - i - 1) * sizeof(htlc));
tal_resize(&cstate->side[creator].htlcs, n-1);
cstate->changes++;
return;
}
}
abort();
} }
void cstate_fail_htlc(struct channel_state *cstate, void cstate_fail_htlc(struct channel_state *cstate,
struct channel_htlc *htlc, struct htlc *htlc,
enum channel_side side) enum channel_side side)
{ {
remove_htlc(cstate, side, side, htlc); remove_htlc(cstate, side, side, htlc);
} }
void cstate_fulfill_htlc(struct channel_state *cstate, void cstate_fulfill_htlc(struct channel_state *cstate,
struct channel_htlc *htlc, struct htlc *htlc,
enum channel_side side) enum channel_side side)
{ {
remove_htlc(cstate, side, !side, htlc); remove_htlc(cstate, side, !side, htlc);
} }
size_t cstate_find_htlc(const struct channel_state *cstate, struct htlc *cstate_find_htlc(const struct channel_state *cstate,
const struct sha256 *rhash, const struct sha256 *rhash,
enum channel_side side) enum channel_side side)
{ {
size_t i; size_t i;
for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) { for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) {
if (structeq(&cstate->side[side].htlcs[i].rhash, rhash)) if (structeq(&cstate->side[side].htlcs[i]->rhash, rhash))
return i; return cstate->side[side].htlcs[i];
} }
return -1; return NULL;
} }
struct channel_htlc *cstate_htlc_by_id(const struct channel_state *cstate, struct htlc *cstate_htlc_by_id(const struct channel_state *cstate,
uint64_t id, uint64_t id,
enum channel_side side) enum channel_side side)
{ {
size_t i; size_t i;
for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) { for (i = 0; i < tal_count(cstate->side[side].htlcs); i++) {
if (cstate->side[side].htlcs[i].id == id) if (cstate->side[side].htlcs[i]->id == id)
return &cstate->side[side].htlcs[i]; return cstate->side[side].htlcs[i];
} }
return NULL; return NULL;
} }
struct channel_state *copy_cstate(const tal_t *ctx, struct channel_state *copy_cstate(const tal_t *ctx,
const struct channel_state *cstate) const struct channel_state *cstate)
{ {
struct channel_state *cs = tal_dup(ctx, struct channel_state, cstate); struct channel_state *cs = tal_dup(ctx, struct channel_state, cstate);
size_t i, j; size_t i;
for (i = 0; i < ARRAY_SIZE(cs->side); i++) { for (i = 0; i < ARRAY_SIZE(cs->side); i++) {
cs->side[i].htlcs = tal_dup_arr(cs, struct channel_htlc, cs->side[i].htlcs = tal_dup_arr(cs, struct htlc *,
cs->side[i].htlcs, cs->side[i].htlcs,
tal_count(cs->side[i].htlcs), 0); tal_count(cs->side[i].htlcs), 0);
for (j = 0; j < tal_count(cs->side[i].htlcs); j++) {
struct channel_htlc *h = &cs->side[i].htlcs[j];
h->routing = tal_dup_arr(cs, u8,
h->routing,
tal_count(h->routing),
0);
}
} }
return cs; return cs;
} }

View File

@@ -2,23 +2,17 @@
#define LIGHTNING_DAEMON_CHANNEL_H #define LIGHTNING_DAEMON_CHANNEL_H
#include "config.h" #include "config.h"
#include "bitcoin/locktime.h" #include "bitcoin/locktime.h"
#include "htlc.h"
#include <ccan/crypto/sha256/sha256.h> #include <ccan/crypto/sha256/sha256.h>
#include <ccan/tal/tal.h> #include <ccan/tal/tal.h>
#include <stdbool.h> #include <stdbool.h>
struct channel_htlc {
u64 id;
u64 msatoshis;
struct abs_locktime expiry;
struct sha256 rhash;
const u8 *routing;
};
struct channel_oneside { struct channel_oneside {
/* Payment and fee is in millisatoshi. */ /* Payment and fee is in millisatoshi. */
uint32_t pay_msat, fee_msat; uint32_t pay_msat, fee_msat;
/* Use tal_count to get the number */ /* Use tal_count to get the number */
struct channel_htlc *htlcs; /* FIXME: Use htlc_map, but needs permute changes. */
struct htlc **htlcs;
}; };
enum channel_side { enum channel_side {
@@ -63,28 +57,17 @@ struct channel_state *copy_cstate(const tal_t *ctx,
/** /**
* cstate_add_htlc: append an HTLC to cstate if it can afford it * cstate_add_htlc: append an HTLC to cstate if it can afford it
* @cstate: The channel state * @cstate: The channel state
* @msatoshis: Millisatoshi going into a HTLC * @htlc: the htlc pointer.
* @expiry: time it expires
* @rhash: hash of redeem secret
* @id: 64-bit ID for htlc
* @routing: onion routing blob
* @routing_len: onion routing blob length
* @side: OURS or THEIRS * @side: OURS or THEIRS
* *
* If that direction can't afford the HTLC (or still owes its half of the fees), * If that direction can't afford the HTLC (or still owes its half of the fees),
* this will return NULL and leave @cstate unchanged. Otherwise * this will return false and leave @cstate unchanged. Otherwise
* cstate->side[dir].htlcs will have the HTLC appended, and pay_msat and * cstate->side[dir].htlcs will have the HTLC appended, and pay_msat and
* fee_msat are adjusted accordingly; &cstate->side[dir].htlcs[<last>] * fee_msat are adjusted accordingly; true is returned.
* is returned.
*/ */
struct channel_htlc *cstate_add_htlc(struct channel_state *cstate, bool cstate_add_htlc(struct channel_state *cstate,
u32 msatoshis, struct htlc *htlc,
const struct abs_locktime *expiry, enum channel_side side);
const struct sha256 *rhash,
uint64_t id,
const u8 *routing,
size_t routing_len,
enum channel_side side);
/** /**
* cstate_fail_htlc: remove an HTLC, funds to the side which offered it. * cstate_fail_htlc: remove an HTLC, funds to the side which offered it.
* @cstate: The channel state * @cstate: The channel state
@@ -95,8 +78,8 @@ struct channel_htlc *cstate_add_htlc(struct channel_state *cstate,
* the value of the HTLC (back) to cstate->side[dir]. * the value of the HTLC (back) to cstate->side[dir].
*/ */
void cstate_fail_htlc(struct channel_state *cstate, void cstate_fail_htlc(struct channel_state *cstate,
struct channel_htlc *htlc, struct htlc *htlc,
enum channel_side side); enum channel_side side);
/** /**
* cstate_fulfill_htlc: remove an HTLC, funds to side which accepted it. * cstate_fulfill_htlc: remove an HTLC, funds to side which accepted it.
@@ -108,8 +91,8 @@ void cstate_fail_htlc(struct channel_state *cstate,
* the value of the HTLC to cstate->side[!dir]. * the value of the HTLC to cstate->side[!dir].
*/ */
void cstate_fulfill_htlc(struct channel_state *cstate, void cstate_fulfill_htlc(struct channel_state *cstate,
struct channel_htlc *htlc, struct htlc *htlc,
enum channel_side side); enum channel_side side);
/** /**
* adjust_fee: Change fee rate. * adjust_fee: Change fee rate.
@@ -135,11 +118,11 @@ bool force_fee(struct channel_state *cstate, uint64_t fee);
* @rhash: hash of redeem secret * @rhash: hash of redeem secret
* @side: OURS or THEIRS * @side: OURS or THEIRS
* *
* Returns a number < tal_count(cstate->side[dir].htlcs), or -1 on fail. * Returns the HTLC, or NULL on fail.
*/ */
size_t cstate_find_htlc(const struct channel_state *cstate, struct htlc *cstate_find_htlc(const struct channel_state *cstate,
const struct sha256 *rhash, const struct sha256 *rhash,
enum channel_side side); enum channel_side side);
/** /**
* cstate_htlc_by_id: find an HTLC on this side of the channel by ID. * cstate_htlc_by_id: find an HTLC on this side of the channel by ID.
@@ -149,9 +132,9 @@ size_t cstate_find_htlc(const struct channel_state *cstate,
* *
* Returns a pointer into cstate->side[@side].htlcs, or NULL. * Returns a pointer into cstate->side[@side].htlcs, or NULL.
*/ */
struct channel_htlc *cstate_htlc_by_id(const struct channel_state *cstate, struct htlc *cstate_htlc_by_id(const struct channel_state *cstate,
uint64_t id, uint64_t id,
enum channel_side side); enum channel_side side);
/** /**
* fee_for_feerate: calculate the fee (in satoshi) for a given fee_rate. * fee_for_feerate: calculate the fee (in satoshi) for a given fee_rate.

View File

@@ -4,6 +4,7 @@
#include "commit_tx.h" #include "commit_tx.h"
#include "controlled_time.h" #include "controlled_time.h"
#include "cryptopkt.h" #include "cryptopkt.h"
#include "htlc.h"
#include "lightningd.h" #include "lightningd.h"
#include "log.h" #include "log.h"
#include "names.h" #include "names.h"
@@ -168,29 +169,23 @@ void queue_pkt_open_complete(struct peer *peer)
queue_pkt(peer, PKT__PKT_OPEN_COMPLETE, o); queue_pkt(peer, PKT__PKT_OPEN_COMPLETE, o);
} }
void queue_pkt_htlc_add(struct peer *peer, void queue_pkt_htlc_add(struct peer *peer, struct htlc *htlc)
u64 id,
u64 msatoshis,
const struct sha256 *rhash,
u32 expiry,
const u8 *route)
{ {
UpdateAddHtlc *u = tal(peer, UpdateAddHtlc); UpdateAddHtlc *u = tal(peer, UpdateAddHtlc);
union htlc_staging stage; union htlc_staging stage;
struct abs_locktime locktime;
struct channel_htlc *htlc;
update_add_htlc__init(u); update_add_htlc__init(u);
u->id = id; u->id = htlc->id;
u->amount_msat = msatoshis; u->amount_msat = htlc->msatoshis;
u->r_hash = sha256_to_proto(u, rhash); u->r_hash = sha256_to_proto(u, &htlc->rhash);
if (!blocks_to_abs_locktime(expiry, &locktime)) u->expiry = abs_locktime_to_proto(u, &htlc->expiry);
fatal("Invalid locktime?");
u->expiry = abs_locktime_to_proto(u, &locktime);
u->route = tal(u, Routing); u->route = tal(u, Routing);
routing__init(u->route); routing__init(u->route);
u->route->info.data = tal_dup_arr(u, u8, route, tal_count(route), 0); u->route->info.data = tal_dup_arr(u, u8,
htlc->routing,
tal_count(htlc->routing),
0);
u->route->info.len = tal_count(u->route->info.data); u->route->info.len = tal_count(u->route->info.data);
/* BOLT #2: /* BOLT #2:
@@ -198,16 +193,11 @@ void queue_pkt_htlc_add(struct peer *peer,
* The sending node MUST add the HTLC addition to the unacked * The sending node MUST add the HTLC addition to the unacked
* changeset for its remote commitment * changeset for its remote commitment
*/ */
htlc = cstate_add_htlc(peer->remote.staging_cstate, if (!cstate_add_htlc(peer->remote.staging_cstate, htlc, OURS))
msatoshis, &locktime, rhash, id,
route, tal_count(route), OURS);
if (!htlc)
fatal("Could not add HTLC?"); fatal("Could not add HTLC?");
stage.add.add = HTLC_ADD; stage.add.add = HTLC_ADD;
/* FIXME: This assumes stage's lifetime >= htlc, since we copy stage.add.htlc = htlc;
* htlc.route pointer. Why not just make stage.add.htlc a ptr? */
stage.add.htlc = *htlc;
add_unacked(&peer->remote, &stage); add_unacked(&peer->remote, &stage);
remote_changes_pending(peer); remote_changes_pending(peer);
@@ -215,14 +205,14 @@ void queue_pkt_htlc_add(struct peer *peer,
queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u); queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u);
} }
void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r) void queue_pkt_htlc_fulfill(struct peer *peer, struct htlc *htlc,
const struct rval *r)
{ {
UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc); UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc);
struct channel_htlc *htlc;
union htlc_staging stage; union htlc_staging stage;
update_fulfill_htlc__init(f); update_fulfill_htlc__init(f);
f->id = id; f->id = htlc->id;
f->r = rval_to_proto(f, r); f->r = rval_to_proto(f, r);
/* BOLT #2: /* BOLT #2:
@@ -230,12 +220,12 @@ void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r)
* The sending node MUST add the HTLC fulfill/fail to the * The sending node MUST add the HTLC fulfill/fail to the
* unacked changeset for its remote commitment * unacked changeset for its remote commitment
*/ */
htlc = cstate_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS); assert(cstate_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS)
assert(htlc); == htlc);
cstate_fulfill_htlc(peer->remote.staging_cstate, htlc, THEIRS); cstate_fulfill_htlc(peer->remote.staging_cstate, htlc, THEIRS);
stage.fulfill.fulfill = HTLC_FULFILL; stage.fulfill.fulfill = HTLC_FULFILL;
stage.fulfill.id = f->id; stage.fulfill.htlc = htlc;
stage.fulfill.r = *r; stage.fulfill.r = *r;
add_unacked(&peer->remote, &stage); add_unacked(&peer->remote, &stage);
@@ -244,14 +234,13 @@ void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r)
queue_pkt(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f); queue_pkt(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f);
} }
void queue_pkt_htlc_fail(struct peer *peer, u64 id) void queue_pkt_htlc_fail(struct peer *peer, struct htlc *htlc)
{ {
UpdateFailHtlc *f = tal(peer, UpdateFailHtlc); UpdateFailHtlc *f = tal(peer, UpdateFailHtlc);
struct channel_htlc *htlc;
union htlc_staging stage; union htlc_staging stage;
update_fail_htlc__init(f); update_fail_htlc__init(f);
f->id = id; f->id = htlc->id;
/* FIXME: reason! */ /* FIXME: reason! */
f->reason = tal(f, FailReason); f->reason = tal(f, FailReason);
@@ -262,12 +251,12 @@ void queue_pkt_htlc_fail(struct peer *peer, u64 id)
* The sending node MUST add the HTLC fulfill/fail to the * The sending node MUST add the HTLC fulfill/fail to the
* unacked changeset for its remote commitment * unacked changeset for its remote commitment
*/ */
htlc = cstate_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS); assert(cstate_htlc_by_id(peer->remote.staging_cstate, f->id, THEIRS)
assert(htlc); == htlc);
cstate_fail_htlc(peer->remote.staging_cstate, htlc, THEIRS); cstate_fail_htlc(peer->remote.staging_cstate, htlc, THEIRS);
stage.fail.fail = HTLC_FAIL; stage.fail.fail = HTLC_FAIL;
stage.fail.id = f->id; stage.fail.htlc = htlc;
add_unacked(&peer->remote, &stage); add_unacked(&peer->remote, &stage);
remote_changes_pending(peer); remote_changes_pending(peer);
@@ -338,41 +327,38 @@ static void apply_changeset(struct peer *peer,
size_t num_changes) size_t num_changes)
{ {
size_t i; size_t i;
struct channel_htlc *htlc; struct htlc *htlc;
for (i = 0; i < num_changes; i++) { for (i = 0; i < num_changes; i++) {
switch (changes[i].type) { switch (changes[i].type) {
case HTLC_ADD: case HTLC_ADD:
htlc = cstate_htlc_by_id(which->staging_cstate, htlc = cstate_htlc_by_id(which->staging_cstate,
changes[i].add.htlc.id, side); changes[i].add.htlc->id, side);
if (htlc) if (htlc)
fatal("Can't add duplicate HTLC id %"PRIu64, fatal("Can't add duplicate HTLC id %"PRIu64,
changes[i].add.htlc.id); changes[i].add.htlc->id);
if (!cstate_add_htlc(which->staging_cstate, if (!cstate_add_htlc(which->staging_cstate,
changes[i].add.htlc.msatoshis, changes[i].add.htlc,
&changes[i].add.htlc.expiry, side))
&changes[i].add.htlc.rhash,
changes[i].add.htlc.id,
changes[i].add.htlc.routing,
tal_count(changes[i].add.htlc.routing),
side))
fatal("Adding HTLC to %s failed", fatal("Adding HTLC to %s failed",
side == OURS ? "ours" : "theirs"); side == OURS ? "ours" : "theirs");
continue; continue;
case HTLC_FAIL: case HTLC_FAIL:
htlc = cstate_htlc_by_id(which->staging_cstate, htlc = cstate_htlc_by_id(which->staging_cstate,
changes[i].fail.id, !side); changes[i].fail.htlc->id,
!side);
if (!htlc) if (!htlc)
fatal("Can't fail non-exisent HTLC id %"PRIu64, fatal("Can't fail non-exisent HTLC id %"PRIu64,
changes[i].fail.id); changes[i].fail.htlc->id);
cstate_fail_htlc(which->staging_cstate, htlc, !side); cstate_fail_htlc(which->staging_cstate, htlc, !side);
continue; continue;
case HTLC_FULFILL: case HTLC_FULFILL:
htlc = cstate_htlc_by_id(which->staging_cstate, htlc = cstate_htlc_by_id(which->staging_cstate,
changes[i].fulfill.id, !side); changes[i].fulfill.htlc->id,
!side);
if (!htlc) if (!htlc)
fatal("Can't fulfill non-exisent HTLC id %"PRIu64, fatal("Can't fulfill non-exisent HTLC id %"PRIu64,
changes[i].fulfill.id); changes[i].fulfill.htlc->id);
cstate_fulfill_htlc(which->staging_cstate, htlc, !side); cstate_fulfill_htlc(which->staging_cstate, htlc, !side);
continue; continue;
} }
@@ -613,7 +599,7 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
const UpdateAddHtlc *u = pkt->update_add_htlc; const UpdateAddHtlc *u = pkt->update_add_htlc;
struct sha256 rhash; struct sha256 rhash;
struct abs_locktime expiry; struct abs_locktime expiry;
struct channel_htlc *htlc; struct htlc *htlc;
union htlc_staging stage; union htlc_staging stage;
/* BOLT #2: /* BOLT #2:
@@ -647,24 +633,17 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
/* Note that it's not *our* problem if they do this, it's /* Note that it's not *our* problem if they do this, it's
* theirs (future confusion). Nonetheless, we detect and * theirs (future confusion). Nonetheless, we detect and
* error for them. */ * error for them. */
if (cstate_htlc_by_id(peer->remote.staging_cstate, u->id, THEIRS) if (htlc_map_get(&peer->remote.htlcs, u->id))
|| cstate_htlc_by_id(peer->remote.commit->cstate, u->id, THEIRS)) {
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id); return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
}
if (cstate_htlc_by_id(peer->local.staging_cstate, u->id, THEIRS)
|| cstate_htlc_by_id(peer->local.commit->cstate, u->id, THEIRS)) {
return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id);
}
/* BOLT #2: /* BOLT #2:
* *
* ...and the receiving node MUST add the HTLC addition to the * ...and the receiving node MUST add the HTLC addition to the
* unacked changeset for its local commitment. */ * unacked changeset for its local commitment. */
htlc = cstate_add_htlc(peer->local.staging_cstate, htlc = peer_new_htlc(peer, u->id, u->amount_msat, &rhash,
u->amount_msat, &expiry, &rhash, u->id, abs_locktime_to_blocks(&expiry),
u->route->info.data, u->route->info.len, u->route->info.data, u->route->info.len,
THEIRS); THEIRS);
/* BOLT #2: /* BOLT #2:
* *
@@ -677,13 +656,15 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
/* FIXME: This is wrong! We may have already added more txs to /* FIXME: This is wrong! We may have already added more txs to
* them.staging_cstate, driving that fee up. * them.staging_cstate, driving that fee up.
* We should check against the last version they acknowledged. */ * We should check against the last version they acknowledged. */
if (!htlc) if (!cstate_add_htlc(peer->local.staging_cstate, htlc, THEIRS)) {
tal_free(htlc);
return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis"
" in your commitment tx", " in your commitment tx",
u->amount_msat); u->amount_msat);
}
stage.add.add = HTLC_ADD; stage.add.add = HTLC_ADD;
stage.add.htlc = *htlc; stage.add.htlc = htlc;
add_unacked(&peer->local, &stage); add_unacked(&peer->local, &stage);
/* FIXME: Fees must be sufficient. */ /* FIXME: Fees must be sufficient. */
@@ -691,18 +672,15 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt)
} }
static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, static Pkt *find_commited_htlc(struct peer *peer, uint64_t id,
struct channel_htlc **local_htlc) struct htlc **local_htlc)
{ {
struct channel_htlc *htlc;
/* BOLT #2: /* BOLT #2:
* *
* A node MUST check that `id` corresponds to an HTLC in its * A node MUST check that `id` corresponds to an HTLC in its
* current commitment transaction, and MUST fail the * current commitment transaction, and MUST fail the
* connection if it does not. * connection if it does not.
*/ */
htlc = cstate_htlc_by_id(peer->local.commit->cstate, id, OURS); if (!cstate_htlc_by_id(peer->local.commit->cstate, id, OURS))
if (!htlc)
return pkt_err(peer, "Did not find HTLC %"PRIu64, id); return pkt_err(peer, "Did not find HTLC %"PRIu64, id);
/* They must not fail/fulfill twice, so it should be in staging, too. */ /* They must not fail/fulfill twice, so it should be in staging, too. */
@@ -716,7 +694,7 @@ static Pkt *find_commited_htlc(struct peer *peer, uint64_t id,
Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt) Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
{ {
const UpdateFailHtlc *f = pkt->update_fail_htlc; const UpdateFailHtlc *f = pkt->update_fail_htlc;
struct channel_htlc *htlc; struct htlc *htlc;
Pkt *err; Pkt *err;
union htlc_staging stage; union htlc_staging stage;
@@ -734,7 +712,7 @@ Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
* to the unacked changeset for its local commitment. * to the unacked changeset for its local commitment.
*/ */
stage.fail.fail = HTLC_FAIL; stage.fail.fail = HTLC_FAIL;
stage.fail.id = f->id; stage.fail.htlc = htlc;
add_unacked(&peer->local, &stage); add_unacked(&peer->local, &stage);
return NULL; return NULL;
} }
@@ -742,7 +720,7 @@ Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt)
Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
{ {
const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc; const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc;
struct channel_htlc *htlc; struct htlc *htlc;
struct sha256 rhash; struct sha256 rhash;
struct rval r; struct rval r;
Pkt *err; Pkt *err;
@@ -767,7 +745,7 @@ Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt)
cstate_fulfill_htlc(peer->local.staging_cstate, htlc, OURS); cstate_fulfill_htlc(peer->local.staging_cstate, htlc, OURS);
stage.fulfill.fulfill = HTLC_FULFILL; stage.fulfill.fulfill = HTLC_FULFILL;
stage.fulfill.id = f->id; stage.fulfill.htlc = htlc;
stage.fulfill.r = r; stage.fulfill.r = r;
add_unacked(&peer->local, &stage); add_unacked(&peer->local, &stage);
return NULL; return NULL;

View File

@@ -535,23 +535,23 @@ static void state_event(struct peer *peer,
} }
/* FIXME: Reason! */ /* FIXME: Reason! */
static bool command_htlc_fail(struct peer *peer, u64 id) static bool command_htlc_fail(struct peer *peer, struct htlc *htlc)
{ {
if (!state_can_remove_htlc(peer->state)) if (!state_can_remove_htlc(peer->state))
return false; return false;
queue_pkt_htlc_fail(peer, id); queue_pkt_htlc_fail(peer, htlc);
return true; return true;
} }
static bool command_htlc_fulfill(struct peer *peer, static bool command_htlc_fulfill(struct peer *peer,
u64 id, struct htlc *htlc,
const struct rval *r) const struct rval *r)
{ {
if (!state_can_remove_htlc(peer->state)) if (!state_can_remove_htlc(peer->state))
return false; return false;
queue_pkt_htlc_fulfill(peer, id, r); queue_pkt_htlc_fulfill(peer, htlc, r);
return true; return true;
} }
@@ -562,6 +562,7 @@ static bool command_htlc_add(struct peer *peer, u64 msatoshis,
{ {
struct channel_state *cstate; struct channel_state *cstate;
struct abs_locktime locktime; struct abs_locktime locktime;
struct htlc *htlc;
if (!blocks_to_abs_locktime(expiry, &locktime)) { if (!blocks_to_abs_locktime(expiry, &locktime)) {
log_unusual(peer->log, "add_htlc: fail: bad expiry %u", expiry); log_unusual(peer->log, "add_htlc: fail: bad expiry %u", expiry);
@@ -580,6 +581,7 @@ static bool command_htlc_add(struct peer *peer, u64 msatoshis,
return false; return false;
} }
/* FIXME: This is wrong: constraint on remote is sufficient. */
/* BOLT #2: /* BOLT #2:
* *
* A node MUST NOT add a HTLC if it would result in it * A node MUST NOT add a HTLC if it would result in it
@@ -597,37 +599,38 @@ static bool command_htlc_add(struct peer *peer, u64 msatoshis,
return false; return false;
} }
htlc = peer_new_htlc(peer, peer->htlc_id_counter,
msatoshis, rhash, expiry, route, tal_count(route),
OURS);
/* FIXME: BOLT is not correct here: we should say IFF we cannot
* afford it in remote at its own current proposed fee-rate. */
/* BOLT #2: /* BOLT #2:
* *
* A node MUST NOT offer `amount_msat` it cannot pay for in * A node MUST NOT offer `amount_msat` it cannot pay for in
* both commitment transactions at the current `fee_rate` * both commitment transactions at the current `fee_rate`
*/ */
cstate = copy_cstate(peer, peer->remote.staging_cstate); cstate = copy_cstate(peer, peer->remote.staging_cstate);
if (!cstate_add_htlc(cstate, msatoshis, if (!cstate_add_htlc(cstate, htlc, OURS)) {
&locktime, rhash, peer->htlc_id_counter,
route, tal_count(route),
OURS)) {
log_unusual(peer->log, "add_htlc: fail: Cannot afford %"PRIu64 log_unusual(peer->log, "add_htlc: fail: Cannot afford %"PRIu64
" milli-satoshis in their commit tx", " milli-satoshis in their commit tx",
msatoshis); msatoshis);
tal_free(htlc);
return false; return false;
} }
tal_free(cstate); tal_free(cstate);
cstate = copy_cstate(peer, peer->local.staging_cstate); cstate = copy_cstate(peer, peer->local.staging_cstate);
if (!cstate_add_htlc(cstate, msatoshis, if (!cstate_add_htlc(cstate, htlc, OURS)) {
&locktime, rhash, peer->htlc_id_counter,
route, tal_count(route),
OURS)) {
log_unusual(peer->log, "add_htlc: fail: Cannot afford %"PRIu64 log_unusual(peer->log, "add_htlc: fail: Cannot afford %"PRIu64
" milli-satoshis in our commit tx", " milli-satoshis in our commit tx",
msatoshis); msatoshis);
tal_free(htlc);
return false; return false;
} }
tal_free(cstate); tal_free(cstate);
queue_pkt_htlc_add(peer, peer->htlc_id_counter, queue_pkt_htlc_add(peer, htlc);
msatoshis, rhash, expiry, route);
/* Make sure we never offer the same one twice. */ /* Make sure we never offer the same one twice. */
peer->htlc_id_counter++; peer->htlc_id_counter++;
@@ -840,7 +843,10 @@ static struct peer *new_peer(struct lightningd_state *dstate,
peer->local.commit = peer->remote.commit = NULL; peer->local.commit = peer->remote.commit = NULL;
peer->local.staging_cstate = peer->remote.staging_cstate = NULL; peer->local.staging_cstate = peer->remote.staging_cstate = NULL;
htlc_map_init(&peer->local.htlcs);
htlc_map_init(&peer->remote.htlcs);
/* FIXME: Attach IO logging for this peer. */ /* FIXME: Attach IO logging for this peer. */
tal_add_destructor(peer, destroy_peer); tal_add_destructor(peer, destroy_peer);
@@ -860,6 +866,41 @@ static struct peer *new_peer(struct lightningd_state *dstate,
return peer; return peer;
} }
static void htlc_destroy(struct htlc *htlc)
{
if (!htlc_map_del(&htlc->peer->local.htlcs, htlc)
&& !htlc_map_del(&htlc->peer->remote.htlcs, htlc))
fatal("Could not find htlc to destroy");
}
struct htlc *peer_new_htlc(struct peer *peer,
u64 id,
u64 msatoshis,
const struct sha256 *rhash,
u32 expiry,
const u8 *route,
size_t routelen,
enum channel_side side)
{
struct htlc *h = tal(peer, struct htlc);
h->peer = peer;
h->id = id;
h->msatoshis = msatoshis;
h->rhash = *rhash;
if (!blocks_to_abs_locktime(expiry, &h->expiry))
fatal("Invalid HTLC expiry %u", expiry);
h->routing = tal_dup_arr(h, u8, route, routelen, 0);
if (side == OURS)
htlc_map_add(&peer->local.htlcs, h);
else {
assert(side == THEIRS);
htlc_map_add(&peer->remote.htlcs, h);
}
tal_add_destructor(h, htlc_destroy);
return h;
}
static struct io_plan *peer_connected_out(struct io_conn *conn, static struct io_plan *peer_connected_out(struct io_conn *conn,
struct lightningd_state *dstate, struct lightningd_state *dstate,
struct json_connecting *connect) struct json_connecting *connect)
@@ -1066,7 +1107,7 @@ again:
/* Check their currently still-existing htlcs for expiry: /* Check their currently still-existing htlcs for expiry:
* We eliminate them from staging as we go. */ * We eliminate them from staging as we go. */
for (i = 0; i < tal_count(peer->remote.staging_cstate->side[THEIRS].htlcs); i++) { for (i = 0; i < tal_count(peer->remote.staging_cstate->side[THEIRS].htlcs); i++) {
struct channel_htlc *htlc = &peer->remote.staging_cstate->side[THEIRS].htlcs[i]; struct htlc *htlc = peer->remote.staging_cstate->side[THEIRS].htlcs[i];
assert(!abs_locktime_is_seconds(&htlc->expiry)); assert(!abs_locktime_is_seconds(&htlc->expiry));
@@ -1076,7 +1117,7 @@ again:
continue; continue;
/* This can fail only if we're in an error state. */ /* This can fail only if we're in an error state. */
if (!command_htlc_fail(peer, htlc->id)) if (!command_htlc_fail(peer, htlc))
return; return;
goto again; goto again;
} }
@@ -1166,8 +1207,7 @@ static bool is_mutual_close(const struct peer *peer,
return false; return false;
} }
static struct channel_htlc *htlc_by_index(const struct commit_info *ci, static struct htlc *htlc_by_index(const struct commit_info *ci, size_t index)
size_t index)
{ {
if (ci->map[index] == -1) if (ci->map[index] == -1)
return NULL; return NULL;
@@ -1177,13 +1217,10 @@ static struct channel_htlc *htlc_by_index(const struct commit_info *ci,
index -= 2; index -= 2;
if (index < tal_count(ci->cstate->side[OURS].htlcs)) if (index < tal_count(ci->cstate->side[OURS].htlcs))
return cast_const(struct channel_htlc *, return ci->cstate->side[OURS].htlcs[index];
ci->cstate->side[OURS].htlcs)
+ index;
index -= tal_count(ci->cstate->side[OURS].htlcs); index -= tal_count(ci->cstate->side[OURS].htlcs);
assert(index < tal_count(ci->cstate->side[THEIRS].htlcs)); assert(index < tal_count(ci->cstate->side[THEIRS].htlcs));
return cast_const(struct channel_htlc *, ci->cstate->side[THEIRS].htlcs) return ci->cstate->side[THEIRS].htlcs[index];
+ index;
} }
static bool htlc_is_ours(const struct commit_info *ci, size_t index) static bool htlc_is_ours(const struct commit_info *ci, size_t index)
@@ -1200,7 +1237,7 @@ static const struct bitcoin_tx *htlc_timeout_tx(const struct peer *peer,
unsigned int i) unsigned int i)
{ {
u8 *wscript; u8 *wscript;
struct channel_htlc *htlc; struct htlc *htlc;
struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1); struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1);
struct bitcoin_signature sig; struct bitcoin_signature sig;
u64 fee, satoshis; u64 fee, satoshis;
@@ -1360,7 +1397,7 @@ static void resolve_cheating(struct peer *peer)
} }
for (i = 2; i < tal_count(ci->map); i++) { for (i = 2; i < tal_count(ci->map); i++) {
struct channel_htlc *h; struct htlc *h;
if (ci->map[i] == -1) if (ci->map[i] == -1)
continue; continue;
@@ -1420,7 +1457,7 @@ static void our_htlc_spent(struct peer *peer,
size_t input_num, size_t input_num,
ptrint_t *pi) ptrint_t *pi)
{ {
struct channel_htlc *h; struct htlc *h;
struct sha256 sha; struct sha256 sha;
struct rval preimage; struct rval preimage;
size_t i = ptr2int(pi); size_t i = ptr2int(pi);
@@ -1475,7 +1512,7 @@ static void our_htlc_depth(struct peer *peer,
bool our_commit, bool our_commit,
size_t i) size_t i)
{ {
struct channel_htlc *h; struct htlc *h;
u32 height; u32 height;
/* Must be in a block. */ /* Must be in a block. */
@@ -1584,7 +1621,7 @@ static void their_htlc_depth(struct peer *peer,
ptrint_t *pi) ptrint_t *pi)
{ {
u32 height; u32 height;
struct channel_htlc *h; struct htlc *h;
size_t i = ptr2int(pi); size_t i = ptr2int(pi);
/* Must be in a block. */ /* Must be in a block. */
@@ -2253,7 +2290,7 @@ static const char *owner_name(enum channel_side side)
} }
static void route_htlc_onwards(struct peer *peer, static void route_htlc_onwards(struct peer *peer,
const struct channel_htlc *htlc, const struct htlc *htlc,
u64 msatoshis, u64 msatoshis,
const BitcoinPubkey *pb_id, const BitcoinPubkey *pb_id,
const u8 *rest_of_route) const u8 *rest_of_route)
@@ -2261,7 +2298,7 @@ static void route_htlc_onwards(struct peer *peer,
/* FIXME: implement */ /* FIXME: implement */
} }
static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc) static void their_htlc_added(struct peer *peer, struct htlc *htlc)
{ {
RouteStep *step; RouteStep *step;
const u8 *rest_of_route; const u8 *rest_of_route;
@@ -2269,7 +2306,7 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
if (abs_locktime_is_seconds(&htlc->expiry)) { if (abs_locktime_is_seconds(&htlc->expiry)) {
log_unusual(peer->log, "HTLC %"PRIu64" is in seconds", htlc->id); log_unusual(peer->log, "HTLC %"PRIu64" is in seconds", htlc->id);
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
return; return;
} }
@@ -2278,7 +2315,7 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
log_unusual(peer->log, "HTLC %"PRIu64" expires too soon:" log_unusual(peer->log, "HTLC %"PRIu64" expires too soon:"
" block %u", " block %u",
htlc->id, abs_locktime_to_blocks(&htlc->expiry)); htlc->id, abs_locktime_to_blocks(&htlc->expiry));
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
return; return;
} }
@@ -2287,7 +2324,7 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
log_unusual(peer->log, "HTLC %"PRIu64" expires too far:" log_unusual(peer->log, "HTLC %"PRIu64" expires too far:"
" block %u", " block %u",
htlc->id, abs_locktime_to_blocks(&htlc->expiry)); htlc->id, abs_locktime_to_blocks(&htlc->expiry));
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
return; return;
} }
@@ -2296,7 +2333,7 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
if (!step) { if (!step) {
log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64, log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64,
htlc->id); htlc->id);
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
return; return;
} }
@@ -2309,7 +2346,7 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
log_add_struct(peer->log, " rhash=%s", log_add_struct(peer->log, " rhash=%s",
struct sha256, &htlc->rhash); struct sha256, &htlc->rhash);
if (unlikely(!peer->dstate->dev_never_routefail)) if (unlikely(!peer->dstate->dev_never_routefail))
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
goto free_rest; goto free_rest;
} }
@@ -2319,13 +2356,13 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
htlc->id, htlc->id,
htlc->msatoshis, htlc->msatoshis,
payment->msatoshis); payment->msatoshis);
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
return; return;
} }
log_info(peer->log, "Immediately resolving HTLC %"PRIu64, log_info(peer->log, "Immediately resolving HTLC %"PRIu64,
htlc->id); htlc->id);
command_htlc_fulfill(peer, htlc->id, &payment->r); command_htlc_fulfill(peer, htlc, &payment->r);
goto free_rest; goto free_rest;
case ROUTE_STEP__NEXT_BITCOIN: case ROUTE_STEP__NEXT_BITCOIN:
@@ -2334,7 +2371,7 @@ static void their_htlc_added(struct peer *peer, const struct channel_htlc *htlc)
goto free_rest; goto free_rest;
default: default:
log_info(peer->log, "Unknown step type %u", step->next_case); log_info(peer->log, "Unknown step type %u", step->next_case);
command_htlc_fail(peer, htlc->id); command_htlc_fail(peer, htlc);
goto free_rest; goto free_rest;
} }
@@ -2357,7 +2394,7 @@ void peer_both_committed_to(struct peer *peer,
switch (changes[i].type) { switch (changes[i].type) {
case HTLC_ADD: case HTLC_ADD:
type = "ADD"; type = "ADD";
htlc_id = changes[i].add.htlc.id; htlc_id = changes[i].add.htlc->id;
owner = owner_name(side); owner = owner_name(side);
assert(cstate_htlc_by_id(peer->remote.commit->cstate, htlc_id, assert(cstate_htlc_by_id(peer->remote.commit->cstate, htlc_id,
side)); side));
@@ -2366,7 +2403,7 @@ void peer_both_committed_to(struct peer *peer,
goto print; goto print;
case HTLC_FAIL: case HTLC_FAIL:
type = "FAIL"; type = "FAIL";
htlc_id = changes[i].fail.id; htlc_id = changes[i].fail.htlc->id;
owner = owner_name(!side); owner = owner_name(!side);
assert(!cstate_htlc_by_id(peer->remote.commit->cstate, htlc_id, assert(!cstate_htlc_by_id(peer->remote.commit->cstate, htlc_id,
!side)); !side));
@@ -2379,7 +2416,7 @@ void peer_both_committed_to(struct peer *peer,
goto print; goto print;
case HTLC_FULFILL: case HTLC_FULFILL:
type = "FULFILL"; type = "FULFILL";
htlc_id = changes[i].fulfill.id; htlc_id = changes[i].fulfill.htlc->id;
owner = owner_name(!side); owner = owner_name(!side);
assert(!cstate_htlc_by_id(peer->remote.commit->cstate, htlc_id, assert(!cstate_htlc_by_id(peer->remote.commit->cstate, htlc_id,
!side)); !side));
@@ -2404,7 +2441,7 @@ void peer_both_committed_to(struct peer *peer,
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
switch (changes[i].type) { switch (changes[i].type) {
case HTLC_ADD: case HTLC_ADD:
their_htlc_added(peer, &changes[i].add.htlc); their_htlc_added(peer, changes[i].add.htlc);
break; break;
case HTLC_FULFILL: case HTLC_FULFILL:
/* FIXME: resolve_one_htlc(peer, id, preimage); */ /* FIXME: resolve_one_htlc(peer, id, preimage); */
@@ -2495,11 +2532,11 @@ static void json_add_htlcs(struct json_result *response,
json_array_start(response, id); json_array_start(response, id);
for (i = 0; i < tal_count(side->htlcs); i++) { for (i = 0; i < tal_count(side->htlcs); i++) {
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_u64(response, "msatoshis", side->htlcs[i].msatoshis); json_add_u64(response, "msatoshis", side->htlcs[i]->msatoshis);
json_add_abstime(response, "expiry", &side->htlcs[i].expiry); json_add_abstime(response, "expiry", &side->htlcs[i]->expiry);
json_add_hex(response, "rhash", json_add_hex(response, "rhash",
&side->htlcs[i].rhash, &side->htlcs[i]->rhash,
sizeof(side->htlcs[i].rhash)); sizeof(side->htlcs[i]->rhash));
json_object_end(response); json_object_end(response);
} }
json_array_end(response); json_array_end(response);
@@ -2648,12 +2685,12 @@ const struct json_command newhtlc_command = {
}; };
/* Looks for their HTLC, but must be committed. */ /* Looks for their HTLC, but must be committed. */
static size_t find_their_committed_htlc(struct peer *peer, static struct htlc *find_their_committed_htlc(struct peer *peer,
const struct sha256 *rhash) const struct sha256 *rhash)
{ {
/* Must be in last committed cstate. */ /* Must be in last committed cstate. */
if (cstate_find_htlc(peer->remote.commit->cstate, rhash, THEIRS) == -1) if (!cstate_find_htlc(peer->remote.commit->cstate, rhash, THEIRS))
return -1; return NULL;
return cstate_find_htlc(peer->remote.staging_cstate, rhash, THEIRS); return cstate_find_htlc(peer->remote.staging_cstate, rhash, THEIRS);
} }
@@ -2665,8 +2702,7 @@ static void json_fulfillhtlc(struct command *cmd,
jsmntok_t *peeridtok, *rtok; jsmntok_t *peeridtok, *rtok;
struct rval r; struct rval r;
struct sha256 rhash; struct sha256 rhash;
size_t i; struct htlc *htlc;
u64 id;
if (!json_get_params(buffer, params, if (!json_get_params(buffer, params,
"peerid", &peeridtok, "peerid", &peeridtok,
@@ -2698,21 +2734,20 @@ static void json_fulfillhtlc(struct command *cmd,
sha256(&rhash, &r, sizeof(r)); sha256(&rhash, &r, sizeof(r));
i = find_their_committed_htlc(peer, &rhash); htlc = find_their_committed_htlc(peer, &rhash);
if (i == -1) { if (!htlc) {
command_fail(cmd, "preimage htlc not found"); command_fail(cmd, "preimage htlc not found");
return; return;
} }
id = peer->remote.staging_cstate->side[THEIRS].htlcs[i].id; if (command_htlc_fulfill(peer, htlc, &r))
if (command_htlc_fulfill(peer, id, &r))
command_success(cmd, null_response(cmd)); command_success(cmd, null_response(cmd));
else else
command_fail(cmd, command_fail(cmd,
"htlc_fulfill not possible in state %s", "htlc_fulfill not possible in state %s",
state_name(peer->state)); state_name(peer->state));
} }
const struct json_command fulfillhtlc_command = { const struct json_command fulfillhtlc_command = {
"fulfillhtlc", "fulfillhtlc",
json_fulfillhtlc, json_fulfillhtlc,
@@ -2726,8 +2761,7 @@ static void json_failhtlc(struct command *cmd,
struct peer *peer; struct peer *peer;
jsmntok_t *peeridtok, *rhashtok; jsmntok_t *peeridtok, *rhashtok;
struct sha256 rhash; struct sha256 rhash;
size_t i; struct htlc *htlc;
u64 id;
if (!json_get_params(buffer, params, if (!json_get_params(buffer, params,
"peerid", &peeridtok, "peerid", &peeridtok,
@@ -2759,20 +2793,19 @@ static void json_failhtlc(struct command *cmd,
/* Look in peer->remote.staging_cstate->a, as that's where we'll /* Look in peer->remote.staging_cstate->a, as that's where we'll
* immediately remove it from: avoids double-handling. */ * immediately remove it from: avoids double-handling. */
i = find_their_committed_htlc(peer, &rhash); htlc = find_their_committed_htlc(peer, &rhash);
if (i == -1) { if (!htlc) {
command_fail(cmd, "htlc not found"); command_fail(cmd, "htlc not found");
return; return;
} }
id = peer->remote.staging_cstate->side[THEIRS].htlcs[i].id; if (command_htlc_fail(peer, htlc))
if (command_htlc_fail(peer, id))
command_success(cmd, null_response(cmd)); command_success(cmd, null_response(cmd));
else else
command_fail(cmd, command_fail(cmd,
"htlc_fail not possible in state %s", "htlc_fail not possible in state %s",
state_name(peer->state)); state_name(peer->state));
} }
const struct json_command failhtlc_command = { const struct json_command failhtlc_command = {
"failhtlc", "failhtlc",
json_failhtlc, json_failhtlc,

View File

@@ -7,6 +7,7 @@
#include "bitcoin/script.h" #include "bitcoin/script.h"
#include "bitcoin/shadouble.h" #include "bitcoin/shadouble.h"
#include "channel.h" #include "channel.h"
#include "htlc.h"
#include "lightning.pb-c.h" #include "lightning.pb-c.h"
#include "netaddr.h" #include "netaddr.h"
#include "protobuf_convert.h" #include "protobuf_convert.h"
@@ -24,18 +25,18 @@ enum htlc_stage_type {
struct htlc_add { struct htlc_add {
enum htlc_stage_type add; enum htlc_stage_type add;
struct channel_htlc htlc; struct htlc *htlc;
}; };
struct htlc_fulfill { struct htlc_fulfill {
enum htlc_stage_type fulfill; enum htlc_stage_type fulfill;
u64 id; struct htlc *htlc;
struct rval r; struct rval r;
}; };
struct htlc_fail { struct htlc_fail {
enum htlc_stage_type fail; enum htlc_stage_type fail;
u64 id; struct htlc *htlc;
}; };
union htlc_staging { union htlc_staging {
@@ -95,6 +96,9 @@ struct peer_visible_state {
/* cstate to generate next commitment tx. */ /* cstate to generate next commitment tx. */
struct channel_state *staging_cstate; struct channel_state *staging_cstate;
/* HTLCs offered by this side */
struct htlc_map htlcs;
}; };
struct out_pkt { struct out_pkt {
@@ -240,6 +244,16 @@ void add_acked_changes(union htlc_staging **acked,
void peer_both_committed_to(struct peer *peer, void peer_both_committed_to(struct peer *peer,
const union htlc_staging *changes, enum channel_side side); const union htlc_staging *changes, enum channel_side side);
/* Freeing removes from map, too */
struct htlc *peer_new_htlc(struct peer *peer,
u64 id,
u64 msatoshis,
const struct sha256 *rhash,
u32 expiry,
const u8 *route,
size_t route_len,
enum channel_side side);
/* Peer has recieved revocation. */ /* Peer has recieved revocation. */
void peer_update_complete(struct peer *peer); void peer_update_complete(struct peer *peer);

12
state.h
View File

@@ -100,14 +100,10 @@ void queue_pkt_open(struct peer *peer, OpenChannel__AnchorOffer anchor);
void queue_pkt_anchor(struct peer *peer); void queue_pkt_anchor(struct peer *peer);
void queue_pkt_open_commit_sig(struct peer *peer); void queue_pkt_open_commit_sig(struct peer *peer);
void queue_pkt_open_complete(struct peer *peer); void queue_pkt_open_complete(struct peer *peer);
void queue_pkt_htlc_add(struct peer *peer, void queue_pkt_htlc_add(struct peer *peer, struct htlc *htlc);
u64 id, void queue_pkt_htlc_fulfill(struct peer *peer, struct htlc *htlc,
u64 msatoshis, const struct rval *r);
const struct sha256 *rhash, void queue_pkt_htlc_fail(struct peer *peer, struct htlc *htlc);
u32 expiry,
const u8 *route);
void queue_pkt_htlc_fulfill(struct peer *peer, u64 id, const struct rval *r);
void queue_pkt_htlc_fail(struct peer *peer, u64 id);
void queue_pkt_commit(struct peer *peer); void queue_pkt_commit(struct peer *peer);
void queue_pkt_revocation(struct peer *peer); void queue_pkt_revocation(struct peer *peer);
void queue_pkt_close_clearing(struct peer *peer); void queue_pkt_close_clearing(struct peer *peer);