lightingd: do a local short_channel_id lookup for forwarding.

Even without optimization, it's faster to walk all the channels than
ping another daemon and wait for the response.

Changelog-Changed: Forwarding messages is now much faster (less inter-daemon traffic)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2020-02-27 14:56:36 +10:30
parent 40e3566e9a
commit f8a21f16c9
8 changed files with 30 additions and 132 deletions

View File

@@ -328,6 +328,22 @@ struct channel *active_channel_by_id(struct lightningd *ld,
return peer_active_channel(peer);
}
struct channel *active_channel_by_scid(struct lightningd *ld,
const struct short_channel_id *scid)
{
struct peer *p;
struct channel *chan;
list_for_each(&ld->peers, p, list) {
list_for_each(&p->channels, chan, list) {
if (channel_active(chan)
&& chan->scid
&& short_channel_id_eq(scid, chan->scid))
return chan;
}
}
return NULL;
}
struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid)
{
struct peer *p;

View File

@@ -214,6 +214,9 @@ struct channel *active_channel_by_id(struct lightningd *ld,
struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid);
struct channel *active_channel_by_scid(struct lightningd *ld,
const struct short_channel_id *scid);
void channel_set_last_tx(struct channel *channel,
struct bitcoin_tx *tx,
const struct bitcoin_signature *sig,

View File

@@ -138,7 +138,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_GETROUTE_REQUEST:
case WIRE_GOSSIP_GETCHANNELS_REQUEST:
case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_GET_CHANNEL_PEER:
case WIRE_GOSSIP_GET_STRIPPED_CUPDATE:
case WIRE_GOSSIP_GET_TXOUT_REPLY:
case WIRE_GOSSIP_OUTPOINT_SPENT:
@@ -155,7 +154,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIP_GETNODES_REPLY:
case WIRE_GOSSIP_GETROUTE_REPLY:
case WIRE_GOSSIP_GETCHANNELS_REPLY:
case WIRE_GOSSIP_GET_CHANNEL_PEER_REPLY:
case WIRE_GOSSIP_GET_INCOMING_CHANNELS_REPLY:
case WIRE_GOSSIP_DEV_MEMLEAK_REPLY:
case WIRE_GOSSIP_DEV_COMPACT_STORE_REPLY:

View File

@@ -1199,14 +1199,10 @@ command_find_channel(struct command *cmd,
tok->end - tok->start,
buffer + tok->start);
} else if (json_to_short_channel_id(buffer, tok, &scid)) {
list_for_each(&ld->peers, peer, list) {
*channel = peer_active_channel(peer);
if (!*channel)
continue;
if ((*channel)->scid
&& (*channel)->scid->u64 == scid.u64)
return NULL;
}
*channel = active_channel_by_scid(ld, &scid);
if (*channel)
return NULL;
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Short channel ID not found: '%.*s'",
tok->end - tok->start,

View File

@@ -657,13 +657,13 @@ static void forward_htlc(struct htlc_in *hin,
u32 cltv_expiry,
struct amount_msat amt_to_forward,
u32 outgoing_cltv_value,
const struct node_id *next_hop,
const struct short_channel_id *scid,
const u8 next_onion[TOTAL_PACKET_SIZE])
{
const u8 *failmsg;
struct amount_msat fee;
struct lightningd *ld = hin->key.channel->peer->ld;
struct channel *next = active_channel_by_id(ld, next_hop, NULL);
struct channel *next = active_channel_by_scid(ld, scid);
struct htlc_out *hout = NULL;
bool needs_update_appended;
@@ -769,50 +769,6 @@ fail:
fromwire_peektype(failmsg));
}
/* Temporary information, while we resolve the next hop */
struct gossip_resolve {
struct short_channel_id next_channel;
struct amount_msat amt_to_forward;
struct amount_msat total_msat;
/* Only set if TLV specifies it */
const struct secret *payment_secret;
u32 outgoing_cltv_value;
u8 *next_onion;
struct htlc_in *hin;
};
/* We received a resolver reply, which gives us the node_ids of the
* channel we want to forward over */
static void channel_resolve_reply(struct subd *gossip, const u8 *msg,
const int *fds UNUSED, struct gossip_resolve *gr)
{
struct node_id *peer_id;
u8 *stripped_update;
if (!fromwire_gossip_get_channel_peer_reply(msg, msg, &peer_id,
&stripped_update)) {
log_broken(gossip->log,
"bad fromwire_gossip_get_channel_peer_reply %s",
tal_hex(msg, msg));
return;
}
if (!peer_id) {
local_fail_in_htlc(gr->hin, take(towire_unknown_next_peer(NULL)));
wallet_forwarded_payment_add(gr->hin->key.channel->peer->ld->wallet,
gr->hin, &gr->next_channel, NULL,
FORWARD_LOCAL_FAILED,
WIRE_UNKNOWN_NEXT_PEER);
tal_free(gr);
return;
}
forward_htlc(gr->hin, gr->hin->cltv_expiry,
gr->amt_to_forward, gr->outgoing_cltv_value, peer_id,
gr->next_onion);
tal_free(gr);
}
/**
* Data passed to the plugin, and as the context for the hook callback
*/
@@ -1014,7 +970,6 @@ htlc_accepted_hook_callback(struct htlc_accepted_hook_payload *request,
struct channel *channel = request->channel;
struct lightningd *ld = request->ld;
struct preimage payment_preimage;
u8 *req;
enum htlc_accepted_result result;
const u8 *failmsg;
result = htlc_accepted_hook_deserialize(request, ld, buffer, toks, &payment_preimage, &failmsg);
@@ -1027,20 +982,11 @@ htlc_accepted_hook_callback(struct htlc_accepted_hook_payload *request,
local_fail_in_htlc_badonion(hin,
WIRE_INVALID_ONION_PAYLOAD);
} else if (rs->nextcase == ONION_FORWARD) {
struct gossip_resolve *gr = tal(ld, struct gossip_resolve);
gr->next_onion = serialize_onionpacket(gr, rs->next);
gr->next_channel = *request->payload->forward_channel;
gr->amt_to_forward = request->payload->amt_to_forward;
gr->outgoing_cltv_value = request->payload->outgoing_cltv;
gr->hin = hin;
req = towire_gossip_get_channel_peer(tmpctx, &gr->next_channel);
log_debug(channel->log, "Asking gossip to resolve channel %s",
type_to_string(tmpctx, struct short_channel_id,
&gr->next_channel));
subd_req(hin, ld->gossip, req, -1, 0,
channel_resolve_reply, gr);
forward_htlc(hin, hin->cltv_expiry,
request->payload->amt_to_forward,
request->payload->outgoing_cltv,
request->payload->forward_channel,
serialize_onionpacket(tmpctx, rs->next));
} else
handle_localpay(hin,
request->payload->amt_to_forward,