htlc: keep channel pointer, not peer pointer.

And move the no-remaining-htlcs check from the peer destructor to the
channel destructor.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-02-12 20:43:04 +10:30 committed by Christian Decker
parent 409fef582d
commit cf7c399cc5
11 changed files with 153 additions and 135 deletions

View File

@ -20,6 +20,33 @@ void channel_set_owner(struct channel *channel, struct subd *owner)
static void destroy_channel(struct channel *channel) static void destroy_channel(struct channel *channel)
{ {
/* Must not have any HTLCs! */
struct htlc_out_map_iter outi;
struct htlc_out *hout;
struct htlc_in_map_iter ini;
struct htlc_in *hin;
struct lightningd *ld = channel->peer->ld;
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
if (hout->key.channel != channel)
continue;
fatal("Freeing channel %s has hout %s",
channel_state_name(channel),
htlc_state_name(hout->hstate));
}
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
if (hin->key.channel != channel)
continue;
fatal("Freeing channel %s has hin %s",
channel_state_name(channel),
htlc_state_name(hin->hstate));
}
/* Free any old owner still hanging around. */ /* Free any old owner still hanging around. */
channel_set_owner(channel, NULL); channel_set_owner(channel, NULL);
@ -112,6 +139,15 @@ struct channel *peer_active_channel(struct peer *peer)
return NULL; return NULL;
} }
struct channel *active_channel_by_id(struct lightningd *ld,
const struct pubkey *id)
{
struct peer *peer = peer_by_id(ld, id);
if (!peer)
return NULL;
return peer_active_channel(peer);
}
void channel_set_state(struct channel *channel, void channel_set_state(struct channel *channel,
enum peer_state old_state, enum peer_state old_state,
enum peer_state state) enum peer_state state)

View File

@ -116,6 +116,9 @@ struct peer *channel2peer(const struct channel *channel);
/* Find a channel which is not onchain, if any */ /* Find a channel which is not onchain, if any */
struct channel *peer_active_channel(struct peer *peer); struct channel *peer_active_channel(struct peer *peer);
struct channel *active_channel_by_id(struct lightningd *ld,
const struct pubkey *id);
static inline bool channel_can_add_htlc(const struct channel *channel) static inline bool channel_can_add_htlc(const struct channel *channel)
{ {
return channel->state == CHANNELD_NORMAL; return channel->state == CHANNELD_NORMAL;

View File

@ -13,18 +13,18 @@ size_t hash_htlc_key(const struct htlc_key *k)
{ {
struct siphash24_ctx ctx; struct siphash24_ctx ctx;
siphash24_init(&ctx, siphash_seed()); siphash24_init(&ctx, siphash_seed());
/* peer doesn't move while in this hash, so we just hash pointer. */ /* channel doesn't move while in this hash, so we just hash pointer. */
siphash24_update(&ctx, &k->peer, sizeof(k->peer)); siphash24_update(&ctx, &k->channel, sizeof(k->channel));
siphash24_u64(&ctx, k->id); siphash24_u64(&ctx, k->id);
return siphash24_done(&ctx); return siphash24_done(&ctx);
} }
struct htlc_in *find_htlc_in(const struct htlc_in_map *map, struct htlc_in *find_htlc_in(const struct htlc_in_map *map,
const struct peer *peer, const struct channel *channel,
u64 htlc_id) u64 htlc_id)
{ {
const struct htlc_key key = { (struct peer *)peer, htlc_id }; const struct htlc_key key = { (struct channel *)channel, htlc_id };
return htlc_in_map_get(map, &key); return htlc_in_map_get(map, &key);
} }
@ -40,10 +40,10 @@ void connect_htlc_in(struct htlc_in_map *map, struct htlc_in *hend)
} }
struct htlc_out *find_htlc_out(const struct htlc_out_map *map, struct htlc_out *find_htlc_out(const struct htlc_out_map *map,
const struct peer *peer, const struct channel *channel,
u64 htlc_id) u64 htlc_id)
{ {
const struct htlc_key key = { (struct peer *)peer, htlc_id }; const struct htlc_key key = { (struct channel *)channel, htlc_id };
return htlc_out_map_get(map, &key); return htlc_out_map_get(map, &key);
} }
@ -91,7 +91,7 @@ struct htlc_in *htlc_in_check(const struct htlc_in *hin, const char *abortstr)
} }
struct htlc_in *new_htlc_in(const tal_t *ctx, struct htlc_in *new_htlc_in(const tal_t *ctx,
struct peer *peer, u64 id, struct channel *channel, u64 id,
u64 msatoshi, u32 cltv_expiry, u64 msatoshi, u32 cltv_expiry,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const struct secret *shared_secret, const struct secret *shared_secret,
@ -100,7 +100,7 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
struct htlc_in *hin = tal(ctx, struct htlc_in); struct htlc_in *hin = tal(ctx, struct htlc_in);
hin->dbid = 0; hin->dbid = 0;
hin->key.peer = peer; hin->key.channel = channel;
hin->key.id = id; hin->key.id = id;
hin->msatoshi = msatoshi; hin->msatoshi = msatoshi;
hin->cltv_expiry = cltv_expiry; hin->cltv_expiry = cltv_expiry;
@ -131,7 +131,7 @@ struct htlc_out *htlc_out_check(const struct htlc_out *hout,
/* You need to set the ID, then connect_htlc_out this! */ /* You need to set the ID, then connect_htlc_out this! */
struct htlc_out *new_htlc_out(const tal_t *ctx, struct htlc_out *new_htlc_out(const tal_t *ctx,
struct peer *peer, struct channel *channel,
u64 msatoshi, u32 cltv_expiry, u64 msatoshi, u32 cltv_expiry,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
@ -142,7 +142,7 @@ struct htlc_out *new_htlc_out(const tal_t *ctx,
/* Mark this as an as of now unsaved HTLC */ /* Mark this as an as of now unsaved HTLC */
hout->dbid = 0; hout->dbid = 0;
hout->key.peer = peer; hout->key.channel = channel;
hout->key.id = HTLC_INVALID_ID; hout->key.id = HTLC_INVALID_ID;
hout->msatoshi = msatoshi; hout->msatoshi = msatoshi;
hout->cltv_expiry = cltv_expiry; hout->cltv_expiry = cltv_expiry;

View File

@ -7,9 +7,9 @@
#include <common/sphinx.h> #include <common/sphinx.h>
#include <wire/gen_onion_wire.h> #include <wire/gen_onion_wire.h>
/* We look up HTLCs by peer & id */ /* We look up HTLCs by channel & id */
struct htlc_key { struct htlc_key {
struct peer *peer; struct channel *channel;
u64 id; u64 id;
}; };
@ -91,13 +91,13 @@ size_t hash_htlc_key(const struct htlc_key *htlc_key);
static inline bool htlc_in_eq(const struct htlc_in *in, const struct htlc_key *k) static inline bool htlc_in_eq(const struct htlc_in *in, const struct htlc_key *k)
{ {
return in->key.peer == k->peer && in->key.id == k->id; return in->key.channel == k->channel && in->key.id == k->id;
} }
static inline bool htlc_out_eq(const struct htlc_out *out, static inline bool htlc_out_eq(const struct htlc_out *out,
const struct htlc_key *k) const struct htlc_key *k)
{ {
return out->key.peer == k->peer && out->key.id == k->id; return out->key.channel == k->channel && out->key.id == k->id;
} }
@ -108,16 +108,16 @@ HTABLE_DEFINE_TYPE(struct htlc_out, keyof_htlc_out, hash_htlc_key, htlc_out_eq,
htlc_out_map); htlc_out_map);
struct htlc_in *find_htlc_in(const struct htlc_in_map *map, struct htlc_in *find_htlc_in(const struct htlc_in_map *map,
const struct peer *peer, const struct channel *channel,
u64 htlc_id); u64 htlc_id);
struct htlc_out *find_htlc_out(const struct htlc_out_map *map, struct htlc_out *find_htlc_out(const struct htlc_out_map *map,
const struct peer *peer, const struct channel *channel,
u64 htlc_id); u64 htlc_id);
/* You still need to connect_htlc_in this! */ /* You still need to connect_htlc_in this! */
struct htlc_in *new_htlc_in(const tal_t *ctx, struct htlc_in *new_htlc_in(const tal_t *ctx,
struct peer *peer, u64 id, struct channel *channel, u64 id,
u64 msatoshi, u32 cltv_expiry, u64 msatoshi, u32 cltv_expiry,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const struct secret *shared_secret, const struct secret *shared_secret,
@ -125,7 +125,7 @@ struct htlc_in *new_htlc_in(const tal_t *ctx,
/* You need to set the ID, then connect_htlc_out this! */ /* You need to set the ID, then connect_htlc_out this! */
struct htlc_out *new_htlc_out(const tal_t *ctx, struct htlc_out *new_htlc_out(const tal_t *ctx,
struct peer *peer, struct channel *channel,
u64 msatoshi, u32 cltv_expiry, u64 msatoshi, u32 cltv_expiry,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,

View File

@ -395,7 +395,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
tal_count(path_secrets), tal_count(path_secrets),
hout->failuremsg); hout->failuremsg);
if (!reply) { if (!reply) {
log_info(hout->key.peer->log, log_info(hout->key.channel->log,
"htlc %"PRIu64" failed with bad reply (%s)", "htlc %"PRIu64" failed with bad reply (%s)",
hout->key.id, hout->key.id,
tal_hex(ltmp, hout->failuremsg)); tal_hex(ltmp, hout->failuremsg));
@ -403,7 +403,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
fail = NULL; fail = NULL;
failcode = WIRE_PERMANENT_NODE_FAILURE; failcode = WIRE_PERMANENT_NODE_FAILURE;
/* Select a channel to mark unroutable by random */ /* Select a channel to mark unroutable by random */
random_mark_channel_unroutable(hout->key.peer->log, random_mark_channel_unroutable(hout->key.channel->log,
ld->gossip, ld->gossip,
payment->route_channels); payment->route_channels);
/* Can now retry; we selected a channel to mark /* Can now retry; we selected a channel to mark
@ -414,7 +414,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout,
report_to_gossipd = false; report_to_gossipd = false;
} else { } else {
failcode = fromwire_peektype(reply->msg); failcode = fromwire_peektype(reply->msg);
log_info(hout->key.peer->log, log_info(hout->key.channel->log,
"htlc %"PRIu64" " "htlc %"PRIu64" "
"failed from %ith node " "failed from %ith node "
"with code 0x%04x (%s)", "with code 0x%04x (%s)",
@ -455,7 +455,6 @@ static bool send_payment(struct command *cmd,
const struct sha256 *rhash, const struct sha256 *rhash,
const struct route_hop *route) const struct route_hop *route)
{ {
struct peer *peer;
const u8 *onion; const u8 *onion;
u8 sessionkey[32]; u8 sessionkey[32];
unsigned int base_expiry; unsigned int base_expiry;
@ -471,6 +470,7 @@ static bool send_payment(struct command *cmd,
struct htlc_out *hout; struct htlc_out *hout;
struct short_channel_id *channels; struct short_channel_id *channels;
struct routing_failure *fail; struct routing_failure *fail;
struct channel *channel;
/* Expiry for HTLCs is absolute. And add one to give some margin. */ /* Expiry for HTLCs is absolute. And add one to give some margin. */
base_expiry = get_block_height(cmd->ld->topology) + 1; base_expiry = get_block_height(cmd->ld->topology) + 1;
@ -534,8 +534,8 @@ static bool send_payment(struct command *cmd,
log_add(cmd->ld->log, "... retrying"); log_add(cmd->ld->log, "... retrying");
} }
peer = peer_by_id(cmd->ld, &ids[0]); channel = active_channel_by_id(cmd->ld, &ids[0]);
if (!peer) { if (!channel) {
/* Report routing failure to gossipd */ /* Report routing failure to gossipd */
fail = immediate_routing_failure(cmd, cmd->ld, fail = immediate_routing_failure(cmd, cmd->ld,
WIRE_UNKNOWN_NEXT_PEER, WIRE_UNKNOWN_NEXT_PEER,
@ -559,7 +559,7 @@ static bool send_payment(struct command *cmd,
log_info(cmd->ld->log, "Sending %u over %zu hops to deliver %u", log_info(cmd->ld->log, "Sending %u over %zu hops to deliver %u",
route[0].amount, n_hops, route[n_hops-1].amount); route[0].amount, n_hops, route[n_hops-1].amount);
failcode = send_htlc_out(peer, route[0].amount, failcode = send_htlc_out(channel, route[0].amount,
base_expiry + route[0].delay, base_expiry + route[0].delay,
rhash, onion, NULL, &hout); rhash, onion, NULL, &hout);
if (failcode) { if (failcode) {

View File

@ -96,32 +96,6 @@ static void peer_set_owner(struct peer *peer, struct subd *owner)
static void destroy_peer(struct peer *peer) static void destroy_peer(struct peer *peer)
{ {
/* Must not have any HTLCs! */
struct htlc_out_map_iter outi;
struct htlc_out *hout;
struct htlc_in_map_iter ini;
struct htlc_in *hin;
for (hout = htlc_out_map_first(&peer->ld->htlcs_out, &outi);
hout;
hout = htlc_out_map_next(&peer->ld->htlcs_out, &outi)) {
if (hout->key.peer != peer)
continue;
fatal("Freeing peer %s has hout %s",
channel_state_name(peer2channel(peer)),
htlc_state_name(hout->hstate));
}
for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini);
hin;
hin = htlc_in_map_next(&peer->ld->htlcs_in, &ini)) {
if (hin->key.peer != peer)
continue;
fatal("Freeing peer %s has hin %s",
channel_state_name(peer2channel(peer)),
htlc_state_name(hin->hstate));
}
list_del_from(&peer->ld->peers, &peer->list); list_del_from(&peer->ld->peers, &peer->list);
} }
@ -887,7 +861,7 @@ static void onchaind_tell_fulfill(struct channel *channel)
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin; hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
if (hin->key.peer != channel2peer(channel)) if (hin->key.channel != channel)
continue; continue;
/* BOLT #5: /* BOLT #5:
@ -1098,7 +1072,7 @@ void free_htlcs(struct lightningd *ld, const struct channel *channel)
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi); for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
hout; hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
if (channel && hout->key.peer != channel2peer(channel)) if (channel && hout->key.channel != channel)
continue; continue;
tal_free(hout); tal_free(hout);
deleted = true; deleted = true;
@ -1107,7 +1081,7 @@ void free_htlcs(struct lightningd *ld, const struct channel *channel)
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin; hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
if (channel && hin->key.peer != channel2peer(channel)) if (channel && hin->key.channel != channel)
continue; continue;
tal_free(hin); tal_free(hin);
deleted = true; deleted = true;

View File

@ -22,12 +22,11 @@
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <wire/gen_onion_wire.h> #include <wire/gen_onion_wire.h>
static bool state_update_ok(struct peer *peer, static bool state_update_ok(struct channel *channel,
enum htlc_state oldstate, enum htlc_state newstate, enum htlc_state oldstate, enum htlc_state newstate,
u64 htlc_id, const char *dir) u64 htlc_id, const char *dir)
{ {
enum htlc_state expected = oldstate + 1; enum htlc_state expected = oldstate + 1;
struct channel *channel = peer2channel(peer);
/* We never get told about RCVD_REMOVE_HTLC, so skip over that /* We never get told about RCVD_REMOVE_HTLC, so skip over that
* (we initialize in SENT_ADD_HTLC / RCVD_ADD_COMMIT, so those * (we initialize in SENT_ADD_HTLC / RCVD_ADD_COMMIT, so those
@ -44,34 +43,37 @@ static bool state_update_ok(struct peer *peer,
return false; return false;
} }
log_debug(peer->log, "HTLC %s %"PRIu64" %s->%s", log_debug(channel->log, "HTLC %s %"PRIu64" %s->%s",
dir, htlc_id, dir, htlc_id,
htlc_state_name(oldstate), htlc_state_name(newstate)); htlc_state_name(oldstate), htlc_state_name(newstate));
return true; return true;
} }
static bool htlc_in_update_state(struct peer *peer, static bool htlc_in_update_state(struct channel *channel,
struct htlc_in *hin, struct htlc_in *hin,
enum htlc_state newstate) enum htlc_state newstate)
{ {
if (!state_update_ok(peer, hin->hstate, newstate, hin->key.id, "in")) if (!state_update_ok(channel, hin->hstate, newstate, hin->key.id, "in"))
return false; return false;
wallet_htlc_update(peer->ld->wallet, hin->dbid, newstate, hin->preimage); wallet_htlc_update(channel->peer->ld->wallet,
hin->dbid, newstate, hin->preimage);
hin->hstate = newstate; hin->hstate = newstate;
htlc_in_check(hin, __func__); htlc_in_check(hin, __func__);
return true; return true;
} }
static bool htlc_out_update_state(struct peer *peer, static bool htlc_out_update_state(struct channel *channel,
struct htlc_out *hout, struct htlc_out *hout,
enum htlc_state newstate) enum htlc_state newstate)
{ {
if (!state_update_ok(peer, hout->hstate, newstate, hout->key.id, "out")) if (!state_update_ok(channel, hout->hstate, newstate, hout->key.id,
"out"))
return false; return false;
wallet_htlc_update(peer->ld->wallet, hout->dbid, newstate, NULL); wallet_htlc_update(channel->peer->ld->wallet, hout->dbid, newstate,
NULL);
hout->hstate = newstate; hout->hstate = newstate;
htlc_out_check(hout, __func__); htlc_out_check(hout, __func__);
@ -97,13 +99,13 @@ static void fail_in_htlc(struct htlc_in *hin,
memset(&hin->failoutchannel, 0, sizeof(hin->failoutchannel)); memset(&hin->failoutchannel, 0, sizeof(hin->failoutchannel));
/* We update state now to signal it's in progress, for persistence. */ /* We update state now to signal it's in progress, for persistence. */
htlc_in_update_state(hin->key.peer, hin, SENT_REMOVE_HTLC); htlc_in_update_state(hin->key.channel, hin, SENT_REMOVE_HTLC);
/* Tell peer, if we can. */ /* Tell peer, if we can. */
if (!peer2channel(hin->key.peer)->owner) if (!hin->key.channel->owner)
return; return;
subd_send_msg(peer2channel(hin->key.peer)->owner, subd_send_msg(hin->key.channel->owner,
take(towire_channel_fail_htlc(hin, take(towire_channel_fail_htlc(hin,
hin->key.id, hin->key.id,
hin->failuremsg, hin->failuremsg,
@ -115,7 +117,7 @@ static void fail_in_htlc(struct htlc_in *hin,
static void local_fail_htlc(struct htlc_in *hin, enum onion_type failcode, static void local_fail_htlc(struct htlc_in *hin, enum onion_type failcode,
const struct short_channel_id *out_channel) const struct short_channel_id *out_channel)
{ {
log_info(hin->key.peer->log, "failed htlc %"PRIu64" code 0x%04x (%s)", log_info(hin->key.channel->log, "failed htlc %"PRIu64" code 0x%04x (%s)",
hin->key.id, failcode, onion_type_name(failcode)); hin->key.id, failcode, onion_type_name(failcode));
fail_in_htlc(hin, failcode, NULL, out_channel); fail_in_htlc(hin, failcode, NULL, out_channel);
@ -128,9 +130,9 @@ static void fail_out_htlc(struct htlc_out *hout, const char *localfail)
assert(hout->failcode || hout->failuremsg); assert(hout->failcode || hout->failuremsg);
if (hout->in) { if (hout->in) {
fail_in_htlc(hout->in, hout->failcode, hout->failuremsg, fail_in_htlc(hout->in, hout->failcode, hout->failuremsg,
peer2channel(hout->key.peer)->scid); hout->key.channel->scid);
} else { } else {
payment_failed(hout->key.peer->ld, hout, localfail); payment_failed(hout->key.channel->peer->ld, hout, localfail);
} }
} }
@ -156,7 +158,7 @@ static bool check_amount(struct htlc_in *hin,
{ {
if (amt_in_htlc - fee >= amt_to_forward) if (amt_in_htlc - fee >= amt_to_forward)
return true; return true;
log_debug(hin->key.peer->ld->log, "HTLC %"PRIu64" incorrect amount:" log_debug(hin->key.channel->log, "HTLC %"PRIu64" incorrect amount:"
" %"PRIu64" in, %"PRIu64" out, fee reqd %"PRIu64, " %"PRIu64" in, %"PRIu64" out, fee reqd %"PRIu64,
hin->key.id, amt_in_htlc, amt_to_forward, fee); hin->key.id, amt_in_htlc, amt_to_forward, fee);
return false; return false;
@ -185,7 +187,7 @@ static bool check_cltv(struct htlc_in *hin,
{ {
if (cltv_expiry - delta >= outgoing_cltv_value) if (cltv_expiry - delta >= outgoing_cltv_value)
return true; return true;
log_debug(hin->key.peer->ld->log, "HTLC %"PRIu64" incorrect CLTV:" log_debug(hin->key.channel->log, "HTLC %"PRIu64" incorrect CLTV:"
" %u in, %u out, delta reqd %u", " %u in, %u out, delta reqd %u",
hin->key.id, cltv_expiry, outgoing_cltv_value, delta); hin->key.id, cltv_expiry, outgoing_cltv_value, delta);
return false; return false;
@ -199,21 +201,21 @@ static void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage)
htlc_in_check(hin, __func__); htlc_in_check(hin, __func__);
/* We update state now to signal it's in progress, for persistence. */ /* We update state now to signal it's in progress, for persistence. */
htlc_in_update_state(hin->key.peer, hin, SENT_REMOVE_HTLC); htlc_in_update_state(hin->key.channel, hin, SENT_REMOVE_HTLC);
/* No owner? We'll either send to channeld in peer_htlcs, or /* No owner? We'll either send to channeld in peer_htlcs, or
* onchaind in onchaind_tell_fulfill. */ * onchaind in onchaind_tell_fulfill. */
if (!peer2channel(hin->key.peer)->owner) { if (!hin->key.channel->owner) {
log_debug(hin->key.peer->log, "HTLC fulfilled, but no owner."); log_debug(hin->key.channel->log, "HTLC fulfilled, but no owner.");
return; return;
} }
if (peer_on_chain(hin->key.peer)) { if (channel_on_chain(hin->key.channel)) {
msg = towire_onchain_known_preimage(hin, preimage); msg = towire_onchain_known_preimage(hin, preimage);
} else { } else {
msg = towire_channel_fulfill_htlc(hin, hin->key.id, preimage); msg = towire_channel_fulfill_htlc(hin, hin->key.id, preimage);
} }
subd_send_msg(peer2channel(hin->key.peer)->owner, take(msg)); subd_send_msg(hin->key.channel->owner, take(msg));
} }
static void handle_localpay(struct htlc_in *hin, static void handle_localpay(struct htlc_in *hin,
@ -224,7 +226,7 @@ static void handle_localpay(struct htlc_in *hin,
{ {
enum onion_type failcode; enum onion_type failcode;
const struct invoice *invoice; const struct invoice *invoice;
struct lightningd *ld = hin->key.peer->ld; struct lightningd *ld = hin->key.channel->peer->ld;
/* BOLT #4: /* BOLT #4:
* *
@ -284,7 +286,7 @@ static void handle_localpay(struct htlc_in *hin,
*/ */
if (get_block_height(ld->topology) + ld->config.cltv_final if (get_block_height(ld->topology) + ld->config.cltv_final
> cltv_expiry) { > cltv_expiry) {
log_debug(hin->key.peer->log, log_debug(hin->key.channel->log,
"Expiry cltv too soon %u < %u + %u", "Expiry cltv too soon %u < %u + %u",
cltv_expiry, cltv_expiry,
get_block_height(ld->topology), get_block_height(ld->topology),
@ -314,7 +316,7 @@ fail:
*/ */
static void hout_subd_died(struct htlc_out *hout) static void hout_subd_died(struct htlc_out *hout)
{ {
log_debug(hout->key.peer->log, log_debug(hout->key.channel->log,
"Failing HTLC %"PRIu64" due to peer death", "Failing HTLC %"PRIu64" due to peer death",
hout->key.id); hout->key.id);
@ -329,6 +331,7 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds,
{ {
u16 failure_code; u16 failure_code;
u8 *failurestr; u8 *failurestr;
struct lightningd *ld = subd->ld;
if (!fromwire_channel_offer_htlc_reply(msg, msg, NULL, if (!fromwire_channel_offer_htlc_reply(msg, msg, NULL,
&hout->key.id, &hout->key.id,
@ -347,17 +350,17 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds,
onion_type_name(failure_code), onion_type_name(failure_code),
(int)tal_len(failurestr), (int)tal_len(failurestr),
(const char *)failurestr); (const char *)failurestr);
payment_failed(hout->key.peer->ld, hout, localfail); payment_failed(ld, hout, localfail);
} else } else
local_fail_htlc(hout->in, failure_code, local_fail_htlc(hout->in, failure_code,
peer2channel(hout->key.peer)->scid); hout->key.channel->scid);
/* Prevent hout from being failed twice. */ /* Prevent hout from being failed twice. */
tal_del_destructor(hout, hout_subd_died); tal_del_destructor(hout, hout_subd_died);
tal_free(hout); tal_free(hout);
return; return;
} }
if (find_htlc_out(&subd->ld->htlcs_out, hout->key.peer, hout->key.id) if (find_htlc_out(&subd->ld->htlcs_out, hout->key.channel, hout->key.id)
|| hout->key.id == HTLC_INVALID_ID) { || hout->key.id == HTLC_INVALID_ID) {
channel_internal_error(subd->channel, channel_internal_error(subd->channel,
"Bad offer_htlc_reply HTLC id %"PRIu64 "Bad offer_htlc_reply HTLC id %"PRIu64
@ -373,36 +376,35 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds,
/* When channeld includes it in commitment, we'll make it persistent. */ /* When channeld includes it in commitment, we'll make it persistent. */
} }
enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv, enum onion_type send_htlc_out(struct channel *out, u64 amount, u32 cltv,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
struct htlc_in *in, struct htlc_in *in,
struct htlc_out **houtp) struct htlc_out **houtp)
{ {
struct htlc_out *hout; struct htlc_out *hout;
struct channel *channel = peer2channel(out);
u8 *msg; u8 *msg;
if (!peer_can_add_htlc(out)) { if (!channel_can_add_htlc(out)) {
log_info(out->log, "Attempt to send HTLC but not ready (%s)", log_info(out->log, "Attempt to send HTLC but not ready (%s)",
peer_state_name(channel->state)); channel_state_name(out));
return WIRE_UNKNOWN_NEXT_PEER; return WIRE_UNKNOWN_NEXT_PEER;
} }
if (!channel->owner) { if (!out->owner) {
log_info(out->log, "Attempt to send HTLC but unowned (%s)", log_info(out->log, "Attempt to send HTLC but unowned (%s)",
peer_state_name(channel->state)); channel_state_name(out));
return WIRE_TEMPORARY_CHANNEL_FAILURE; return WIRE_TEMPORARY_CHANNEL_FAILURE;
} }
/* Make peer's daemon own it, catch if it dies. */ /* Make peer's daemon own it, catch if it dies. */
hout = new_htlc_out(channel->owner, out, amount, cltv, hout = new_htlc_out(out->owner, out, amount, cltv,
payment_hash, onion_routing_packet, in); payment_hash, onion_routing_packet, in);
tal_add_destructor(hout, hout_subd_died); tal_add_destructor(hout, hout_subd_died);
msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash, msg = towire_channel_offer_htlc(out, amount, cltv, payment_hash,
onion_routing_packet); onion_routing_packet);
subd_req(out->ld, channel->owner, take(msg), -1, 0, rcvd_htlc_reply, hout); subd_req(out->peer->ld, out->owner, take(msg), -1, 0, rcvd_htlc_reply, hout);
if (houtp) if (houtp)
*houtp = hout; *houtp = hout;
@ -419,11 +421,11 @@ static void forward_htlc(struct htlc_in *hin,
{ {
enum onion_type failcode; enum onion_type failcode;
u64 fee; u64 fee;
struct lightningd *ld = hin->key.peer->ld; struct lightningd *ld = hin->key.channel->peer->ld;
struct peer *next = peer_by_id(ld, next_hop); struct channel *next = active_channel_by_id(ld, next_hop);
/* Unknown peer, or peer not ready. */ /* Unknown peer, or peer not ready. */
if (!next || !peer2channel(next)->scid) { if (!next || !next->scid) {
local_fail_htlc(hin, WIRE_UNKNOWN_NEXT_PEER, NULL); local_fail_htlc(hin, WIRE_UNKNOWN_NEXT_PEER, NULL);
return; return;
} }
@ -461,11 +463,11 @@ static void forward_htlc(struct htlc_in *hin,
*/ */
/* In our case, G = 1, so we need to expire it one after it's expiration. /* In our case, G = 1, so we need to expire it one after it's expiration.
* But never offer an expired HTLC; that's dumb. */ * But never offer an expired HTLC; that's dumb. */
if (get_block_height(next->ld->topology) >= outgoing_cltv_value) { if (get_block_height(ld->topology) >= outgoing_cltv_value) {
log_debug(hin->key.peer->log, log_debug(hin->key.channel->log,
"Expiry cltv %u too close to current %u", "Expiry cltv %u too close to current %u",
outgoing_cltv_value, outgoing_cltv_value,
get_block_height(next->ld->topology)); get_block_height(ld->topology));
failcode = WIRE_EXPIRY_TOO_SOON; failcode = WIRE_EXPIRY_TOO_SOON;
goto fail; goto fail;
} }
@ -476,13 +478,13 @@ static void forward_htlc(struct htlc_in *hin,
* *
* 1. type: 21 (`expiry_too_far`) * 1. type: 21 (`expiry_too_far`)
*/ */
if (get_block_height(next->ld->topology) if (get_block_height(ld->topology)
+ next->ld->config.max_htlc_expiry < outgoing_cltv_value) { + ld->config.max_htlc_expiry < outgoing_cltv_value) {
log_debug(hin->key.peer->log, log_debug(hin->key.channel->log,
"Expiry cltv %u too far from current %u + max %u", "Expiry cltv %u too far from current %u + max %u",
outgoing_cltv_value, outgoing_cltv_value,
get_block_height(next->ld->topology), get_block_height(ld->topology),
next->ld->config.max_htlc_expiry); ld->config.max_htlc_expiry);
failcode = WIRE_EXPIRY_TOO_FAR; failcode = WIRE_EXPIRY_TOO_FAR;
goto fail; goto fail;
} }
@ -494,7 +496,7 @@ static void forward_htlc(struct htlc_in *hin,
return; return;
fail: fail:
local_fail_htlc(hin, failcode, peer2channel(next)->scid); local_fail_htlc(hin, failcode, next->scid);
} }
/* Temporary information, while we resolve the next hop */ /* Temporary information, while we resolve the next hop */
@ -555,14 +557,14 @@ static bool peer_accepted_htlc(struct peer *peer,
const tal_t *tmpctx = tal_tmpctx(peer); const tal_t *tmpctx = tal_tmpctx(peer);
struct channel *channel = peer2channel(peer); struct channel *channel = peer2channel(peer);
hin = find_htlc_in(&peer->ld->htlcs_in, peer, id); hin = find_htlc_in(&peer->ld->htlcs_in, channel, id);
if (!hin) { if (!hin) {
channel_internal_error(channel, channel_internal_error(channel,
"peer_got_revoke unknown htlc %"PRIu64, id); "peer_got_revoke unknown htlc %"PRIu64, id);
return false; return false;
} }
if (!htlc_in_update_state(peer, hin, RCVD_ADD_ACK_REVOCATION)) if (!htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION))
return false; return false;
/* BOLT #2: /* BOLT #2:
@ -673,7 +675,7 @@ static bool peer_fulfilled_our_htlc(struct channel *channel,
struct htlc_out *hout; struct htlc_out *hout;
struct peer *peer = channel2peer(channel); struct peer *peer = channel2peer(channel);
hout = find_htlc_out(&peer->ld->htlcs_out, peer, fulfilled->id); hout = find_htlc_out(&peer->ld->htlcs_out, channel, fulfilled->id);
if (!hout) { if (!hout) {
channel_internal_error(channel, channel_internal_error(channel,
"fulfilled_our_htlc unknown htlc %"PRIu64, "fulfilled_our_htlc unknown htlc %"PRIu64,
@ -681,7 +683,7 @@ static bool peer_fulfilled_our_htlc(struct channel *channel,
return false; return false;
} }
if (!htlc_out_update_state(peer, hout, RCVD_REMOVE_COMMIT)) if (!htlc_out_update_state(channel, hout, RCVD_REMOVE_COMMIT))
return false; return false;
fulfill_our_htlc_out(peer, hout, &fulfilled->payment_preimage); fulfill_our_htlc_out(peer, hout, &fulfilled->payment_preimage);
@ -702,7 +704,7 @@ void onchain_fulfilled_htlc(struct channel *channel,
for (hout = htlc_out_map_first(&ld->htlcs_out, &outi); for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
hout; hout;
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
if (hout->key.peer != channel2peer(channel)) if (hout->key.channel != channel)
continue; continue;
if (!structeq(&hout->payment_hash, &payment_hash)) if (!structeq(&hout->payment_hash, &payment_hash))
@ -724,7 +726,7 @@ static bool peer_failed_our_htlc(struct channel *channel,
struct htlc_out *hout; struct htlc_out *hout;
struct peer *peer = channel2peer(channel); struct peer *peer = channel2peer(channel);
hout = find_htlc_out(&peer->ld->htlcs_out, peer, failed->id); hout = find_htlc_out(&peer->ld->htlcs_out, channel, failed->id);
if (!hout) { if (!hout) {
channel_internal_error(channel, channel_internal_error(channel,
"failed_our_htlc unknown htlc %"PRIu64, "failed_our_htlc unknown htlc %"PRIu64,
@ -732,7 +734,7 @@ static bool peer_failed_our_htlc(struct channel *channel,
return false; return false;
} }
if (!htlc_out_update_state(peer, hout, RCVD_REMOVE_COMMIT)) if (!htlc_out_update_state(channel, hout, RCVD_REMOVE_COMMIT))
return false; return false;
hout->failcode = failed->malformed; hout->failcode = failed->malformed;
@ -762,7 +764,7 @@ struct htlc_out *find_htlc_out_by_ripemd(const struct channel *channel,
hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
struct ripemd160 hash; struct ripemd160 hash;
if (hout->key.peer != channel2peer(channel)) if (hout->key.channel != channel)
continue; continue;
ripemd160(&hash, ripemd160(&hash,
@ -789,11 +791,11 @@ void onchain_failed_our_htlc(const struct channel *channel,
char *localfail = tal_fmt(channel, "%s: %s", char *localfail = tal_fmt(channel, "%s: %s",
onion_type_name(WIRE_PERMANENT_CHANNEL_FAILURE), onion_type_name(WIRE_PERMANENT_CHANNEL_FAILURE),
why); why);
payment_failed(hout->key.peer->ld, hout, localfail); payment_failed(hout->key.channel->peer->ld, hout, localfail);
tal_free(localfail); tal_free(localfail);
} else } else
local_fail_htlc(hout->in, WIRE_PERMANENT_CHANNEL_FAILURE, local_fail_htlc(hout->in, WIRE_PERMANENT_CHANNEL_FAILURE,
peer2channel(hout->key.peer)->scid); hout->key.channel->scid);
} }
static void remove_htlc_in(struct peer *peer, struct htlc_in *hin) static void remove_htlc_in(struct peer *peer, struct htlc_in *hin)
@ -847,13 +849,13 @@ static bool update_in_htlc(struct peer *peer, u64 id, enum htlc_state newstate)
struct htlc_in *hin; struct htlc_in *hin;
struct channel *channel = peer2channel(peer); struct channel *channel = peer2channel(peer);
hin = find_htlc_in(&peer->ld->htlcs_in, peer, id); hin = find_htlc_in(&peer->ld->htlcs_in, channel, id);
if (!hin) { if (!hin) {
channel_internal_error(channel, "Can't find in HTLC %"PRIu64, id); channel_internal_error(channel, "Can't find in HTLC %"PRIu64, id);
return false; return false;
} }
if (!htlc_in_update_state(peer, hin, newstate)) if (!htlc_in_update_state(channel, hin, newstate))
return false; return false;
if (newstate == SENT_REMOVE_ACK_REVOCATION) if (newstate == SENT_REMOVE_ACK_REVOCATION)
@ -867,7 +869,7 @@ static bool update_out_htlc(struct peer *peer, u64 id, enum htlc_state newstate)
struct htlc_out *hout; struct htlc_out *hout;
struct channel *channel = peer2channel(peer); struct channel *channel = peer2channel(peer);
hout = find_htlc_out(&peer->ld->htlcs_out, peer, id); hout = find_htlc_out(&peer->ld->htlcs_out, channel, id);
if (!hout) { if (!hout) {
channel_internal_error(channel, "Can't find out HTLC %"PRIu64, id); channel_internal_error(channel, "Can't find out HTLC %"PRIu64, id);
return false; return false;
@ -882,7 +884,7 @@ static bool update_out_htlc(struct peer *peer, u64 id, enum htlc_state newstate)
&hout->payment_hash); &hout->payment_hash);
} }
if (!htlc_out_update_state(peer, hout, newstate)) if (!htlc_out_update_state(channel, hout, newstate))
return false; return false;
/* First transition into commitment; now it outlives peer. */ /* First transition into commitment; now it outlives peer. */
@ -1034,7 +1036,7 @@ static bool channel_added_their_htlc(struct channel *channel,
/* This stays around even if we fail it immediately: it *is* /* This stays around even if we fail it immediately: it *is*
* part of the current commitment. */ * part of the current commitment. */
hin = new_htlc_in(channel, channel2peer(channel), added->id, added->amount_msat, hin = new_htlc_in(channel, channel, added->id, added->amount_msat,
added->cltv_expiry, &added->payment_hash, added->cltv_expiry, &added->payment_hash,
shared_secret, added->onion_routing_packet); shared_secret, added->onion_routing_packet);
@ -1271,7 +1273,7 @@ void peer_got_revoke(struct channel *channel, const u8 *msg)
/* These are all errors before finding next hop. */ /* These are all errors before finding next hop. */
assert(!(failcodes[i] & UPDATE)); assert(!(failcodes[i] & UPDATE));
hin = find_htlc_in(&ld->htlcs_in, channel2peer(channel), changed[i].id); hin = find_htlc_in(&ld->htlcs_in, channel, changed[i].id);
local_fail_htlc(hin, failcodes[i], NULL); local_fail_htlc(hin, failcodes[i], NULL);
} }
wallet_channel_save(ld->wallet, channel); wallet_channel_save(ld->wallet, channel);
@ -1356,6 +1358,8 @@ void peer_htlcs(const tal_t *ctx,
struct htlc_out_map_iter outi; struct htlc_out_map_iter outi;
struct htlc_in *hin; struct htlc_in *hin;
struct htlc_out *hout; struct htlc_out *hout;
struct channel *channel = peer2channel(peer);
struct lightningd *ld = channel->peer->ld;
*htlcs = tal_arr(ctx, struct added_htlc, 0); *htlcs = tal_arr(ctx, struct added_htlc, 0);
*htlc_states = tal_arr(ctx, enum htlc_state, 0); *htlc_states = tal_arr(ctx, enum htlc_state, 0);
@ -1364,10 +1368,10 @@ void peer_htlcs(const tal_t *ctx,
*failed_htlcs = tal_arr(ctx, const struct failed_htlc *, 0); *failed_htlcs = tal_arr(ctx, const struct failed_htlc *, 0);
*failed_sides = tal_arr(ctx, enum side, 0); *failed_sides = tal_arr(ctx, enum side, 0);
for (hin = htlc_in_map_first(&peer->ld->htlcs_in, &ini); for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin; hin;
hin = htlc_in_map_next(&peer->ld->htlcs_in, &ini)) { hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
if (hin->key.peer != peer) if (hin->key.channel != channel)
continue; continue;
add_htlc(htlcs, htlc_states, add_htlc(htlcs, htlc_states,
@ -1383,10 +1387,10 @@ void peer_htlcs(const tal_t *ctx,
fulfilled_htlcs, fulfilled_sides); fulfilled_htlcs, fulfilled_sides);
} }
for (hout = htlc_out_map_first(&peer->ld->htlcs_out, &outi); for (hout = htlc_out_map_first(&ld->htlcs_out, &outi);
hout; hout;
hout = htlc_out_map_next(&peer->ld->htlcs_out, &outi)) { hout = htlc_out_map_next(&ld->htlcs_out, &outi)) {
if (hout->key.peer != peer) if (hout->key.channel != channel)
continue; continue;
add_htlc(htlcs, htlc_states, add_htlc(htlcs, htlc_states,
@ -1454,14 +1458,14 @@ void notify_new_block(struct lightningd *ld, u32 height)
continue; continue;
/* Peer on chain already? */ /* Peer on chain already? */
if (peer_on_chain(hout->key.peer)) if (channel_on_chain(hout->key.channel))
continue; continue;
/* Peer already failed, or we hit it? */ /* Peer already failed, or we hit it? */
if (peer2channel(hout->key.peer)->error) if (hout->key.channel->error)
continue; continue;
channel_fail_permanent(peer2channel(hout->key.peer), channel_fail_permanent(hout->key.channel,
"Offered HTLC %"PRIu64 "Offered HTLC %"PRIu64
" %s cltv %u hit deadline", " %s cltv %u hit deadline",
hout->key.id, hout->key.id,
@ -1489,7 +1493,7 @@ void notify_new_block(struct lightningd *ld, u32 height)
for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); for (hin = htlc_in_map_first(&ld->htlcs_in, &ini);
hin; hin;
hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { hin = htlc_in_map_next(&ld->htlcs_in, &ini)) {
struct channel *channel = peer2channel(hin->key.peer); struct channel *channel = hin->key.channel;
/* Not fulfilled? If overdue, that's their problem... */ /* Not fulfilled? If overdue, that's their problem... */
if (!hin->preimage) if (!hin->preimage)

View File

@ -35,7 +35,7 @@ void peer_got_revoke(struct channel *channel, const u8 *msg);
void update_per_commit_point(struct peer *peer, void update_per_commit_point(struct peer *peer,
const struct pubkey *per_commitment_point); const struct pubkey *per_commitment_point);
enum onion_type send_htlc_out(struct peer *out, u64 amount, u32 cltv, enum onion_type send_htlc_out(struct channel *out, u64 amount, u32 cltv,
const struct sha256 *payment_hash, const struct sha256 *payment_hash,
const u8 *onion_routing_packet, const u8 *onion_routing_packet,
struct htlc_in *in, struct htlc_in *in,

View File

@ -1015,12 +1015,12 @@ static bool test_htlc_crud(struct lightningd *ld, const tal_t *ctx)
memset(&out.payment_hash, 'A', sizeof(struct sha256)); memset(&out.payment_hash, 'A', sizeof(struct sha256));
memset(&payment_key, 'B', sizeof(payment_key)); memset(&payment_key, 'B', sizeof(payment_key));
in.key.id = 42; in.key.id = 42;
in.key.peer = peer; in.key.channel = chan;
in.msatoshi = 42; in.msatoshi = 42;
out.in = &in; out.in = &in;
out.key.id = 1337; out.key.id = 1337;
out.key.peer = peer; out.key.channel = chan;
out.msatoshi = 41; out.msatoshi = 41;
/* Store the htlc_in */ /* Store the htlc_in */

View File

@ -1053,13 +1053,13 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid,
db_exec_prepared(wallet->db, stmt); db_exec_prepared(wallet->db, stmt);
} }
static bool wallet_stmt2htlc_in(const struct channel *channel, static bool wallet_stmt2htlc_in(struct channel *channel,
sqlite3_stmt *stmt, struct htlc_in *in) sqlite3_stmt *stmt, struct htlc_in *in)
{ {
bool ok = true; bool ok = true;
in->dbid = sqlite3_column_int64(stmt, 0); in->dbid = sqlite3_column_int64(stmt, 0);
in->key.id = sqlite3_column_int64(stmt, 1); in->key.id = sqlite3_column_int64(stmt, 1);
in->key.peer = channel2peer(channel); in->key.channel = channel;
in->msatoshi = sqlite3_column_int64(stmt, 2); in->msatoshi = sqlite3_column_int64(stmt, 2);
in->cltv_expiry = sqlite3_column_int(stmt, 3); in->cltv_expiry = sqlite3_column_int(stmt, 3);
in->hstate = sqlite3_column_int(stmt, 4); in->hstate = sqlite3_column_int(stmt, 4);
@ -1087,13 +1087,13 @@ static bool wallet_stmt2htlc_in(const struct channel *channel,
return ok; return ok;
} }
static bool wallet_stmt2htlc_out(const struct channel *channel, static bool wallet_stmt2htlc_out(struct channel *channel,
sqlite3_stmt *stmt, struct htlc_out *out) sqlite3_stmt *stmt, struct htlc_out *out)
{ {
bool ok = true; bool ok = true;
out->dbid = sqlite3_column_int64(stmt, 0); out->dbid = sqlite3_column_int64(stmt, 0);
out->key.id = sqlite3_column_int64(stmt, 1); out->key.id = sqlite3_column_int64(stmt, 1);
out->key.peer = channel2peer(channel); out->key.channel = channel;
out->msatoshi = sqlite3_column_int64(stmt, 2); out->msatoshi = sqlite3_column_int64(stmt, 2);
out->cltv_expiry = sqlite3_column_int(stmt, 3); out->cltv_expiry = sqlite3_column_int(stmt, 3);
out->hstate = sqlite3_column_int(stmt, 4); out->hstate = sqlite3_column_int(stmt, 4);

View File

@ -18,6 +18,7 @@ struct invoices;
struct channel; struct channel;
struct lightningd; struct lightningd;
struct oneshot; struct oneshot;
struct peer;
struct pubkey; struct pubkey;
struct timers; struct timers;