mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
gossipd: simplify channel_announce handling.
We make new_routing_channel() populate both connections (active=false), so local_add_channel becomes simpler. We also suppress listchannels output of active=false unannounced channels, to avoid breaking tests (also, these are unusable, so it makes sense to omit them) It also seems the logic in add_channel_direction is legacy: a channel_announce cannot replace the scid (that would be a different channel), we don't allow duplicate announcements, and the announcement is never NULL. And since we disallow repeated channel_announce already, I believe 'forward' is always true, greatly simplifying the logic in handle_pending_cannouncement. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
6dec2ed1c1
commit
942d04ba87
@@ -763,10 +763,12 @@ static void handle_local_add_channel(struct peer *peer, u8 *msg)
|
|||||||
struct short_channel_id scid;
|
struct short_channel_id scid;
|
||||||
struct bitcoin_blkid chain_hash;
|
struct bitcoin_blkid chain_hash;
|
||||||
struct pubkey remote_node_id;
|
struct pubkey remote_node_id;
|
||||||
u16 cltv_expiry_delta, direction;
|
u16 cltv_expiry_delta;
|
||||||
u32 fee_base_msat, fee_proportional_millionths;
|
u32 fee_base_msat, fee_proportional_millionths;
|
||||||
u64 htlc_minimum_msat;
|
u64 htlc_minimum_msat;
|
||||||
|
int idx;
|
||||||
struct node_connection *c;
|
struct node_connection *c;
|
||||||
|
struct routing_channel *chan;
|
||||||
|
|
||||||
if (!fromwire_gossip_local_add_channel(
|
if (!fromwire_gossip_local_add_channel(
|
||||||
msg, &scid, &chain_hash, &remote_node_id,
|
msg, &scid, &chain_hash, &remote_node_id,
|
||||||
@@ -788,9 +790,13 @@ static void handle_local_add_channel(struct peer *peer, u8 *msg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
direction = get_channel_direction(&rstate->local_id, &remote_node_id);
|
/* Create new routing channel */
|
||||||
c = half_add_connection(rstate, &peer->daemon->id, &remote_node_id,
|
chan = new_routing_channel(rstate, &scid,
|
||||||
&scid);
|
&rstate->local_id, &remote_node_id);
|
||||||
|
|
||||||
|
idx = pubkey_idx(&rstate->local_id, &remote_node_id);
|
||||||
|
c = chan->connections[idx];
|
||||||
|
|
||||||
/* FIXME: Deduplicate with code in routing.c */
|
/* FIXME: Deduplicate with code in routing.c */
|
||||||
c->active = true;
|
c->active = true;
|
||||||
c->last_timestamp = 0;
|
c->last_timestamp = 0;
|
||||||
@@ -801,7 +807,7 @@ static void handle_local_add_channel(struct peer *peer, u8 *msg)
|
|||||||
/* Designed to match msg in handle_channel_update, for easy testing */
|
/* Designed to match msg in handle_channel_update, for easy testing */
|
||||||
status_trace("Received local update for channel %s(%d) now ACTIVE",
|
status_trace("Received local update for channel %s(%d) now ACTIVE",
|
||||||
type_to_string(msg, struct short_channel_id, &scid),
|
type_to_string(msg, struct short_channel_id, &scid),
|
||||||
direction);
|
idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1083,6 +1089,10 @@ static void append_half_channel(struct gossip_getchannels_entry **entries,
|
|||||||
if (!c)
|
if (!c)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Don't mention non-public inactive channels. */
|
||||||
|
if (!c->active && !c->channel_update)
|
||||||
|
return;
|
||||||
|
|
||||||
n = tal_count(*entries);
|
n = tal_count(*entries);
|
||||||
tal_resize(entries, n+1);
|
tal_resize(entries, n+1);
|
||||||
e = &(*entries)[n];
|
e = &(*entries)[n];
|
||||||
@@ -1375,6 +1385,7 @@ static void gossip_prune_network(struct daemon *daemon)
|
|||||||
|
|
||||||
nc = connection_from(n, n->channels[i]);
|
nc = connection_from(n, n->channels[i]);
|
||||||
|
|
||||||
|
/* FIXME: We still need to prune announced-but-not-updated channels after some time. */
|
||||||
if (!nc || !nc->channel_update) {
|
if (!nc || !nc->channel_update) {
|
||||||
/* Not even announced yet */
|
/* Not even announced yet */
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -194,44 +194,6 @@ static void destroy_routing_channel(struct routing_channel *chan,
|
|||||||
tal_free(chan->nodes[1]);
|
tal_free(chan->nodes[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns routing_channel connecting from and to: *idx set to refer
|
|
||||||
* to connection with src=from, dst=to */
|
|
||||||
static struct routing_channel *find_channel(struct routing_state *rstate,
|
|
||||||
const struct node *from,
|
|
||||||
const struct node *to,
|
|
||||||
int *idx)
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
*idx = pubkey_idx(&from->id, &to->id);
|
|
||||||
|
|
||||||
n = tal_count(to->channels);
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
if (to->channels[i]->nodes[*idx] == from)
|
|
||||||
return to->channels[i];
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct node_connection *get_connection(struct routing_state *rstate,
|
|
||||||
const struct pubkey *from_id,
|
|
||||||
const struct pubkey *to_id)
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
struct node *from, *to;
|
|
||||||
struct routing_channel *c;
|
|
||||||
|
|
||||||
from = get_node(rstate, from_id);
|
|
||||||
to = get_node(rstate, to_id);
|
|
||||||
if (!from || ! to)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
c = find_channel(rstate, from, to, &idx);
|
|
||||||
if (!c)
|
|
||||||
return NULL;
|
|
||||||
return c->connections[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: All users of this are confused. */
|
/* FIXME: All users of this are confused. */
|
||||||
struct node_connection *get_connection_by_scid(const struct routing_state *rstate,
|
struct node_connection *get_connection_by_scid(const struct routing_state *rstate,
|
||||||
const struct short_channel_id *scid,
|
const struct short_channel_id *scid,
|
||||||
@@ -284,24 +246,31 @@ static struct node_connection *new_node_connection(struct routing_state *rstate,
|
|||||||
c->last_timestamp = -1;
|
c->last_timestamp = -1;
|
||||||
|
|
||||||
/* Hook it into in/out arrays. */
|
/* Hook it into in/out arrays. */
|
||||||
assert(!chan->connections[idx]);
|
|
||||||
chan->connections[idx] = c;
|
chan->connections[idx] = c;
|
||||||
|
|
||||||
tal_add_destructor2(c, destroy_node_connection, chan);
|
tal_add_destructor2(c, destroy_node_connection, chan);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct routing_channel *new_routing_channel(struct routing_state *rstate,
|
struct routing_channel *new_routing_channel(struct routing_state *rstate,
|
||||||
const struct short_channel_id *scid,
|
const struct short_channel_id *scid,
|
||||||
struct node *n1,
|
const struct pubkey *id1,
|
||||||
struct node *n2)
|
const struct pubkey *id2)
|
||||||
{
|
{
|
||||||
struct routing_channel *chan = tal(rstate, struct routing_channel);
|
struct routing_channel *chan = tal(rstate, struct routing_channel);
|
||||||
int n1idx = pubkey_idx(&n1->id, &n2->id);
|
int n1idx = pubkey_idx(id1, id2);
|
||||||
size_t n;
|
size_t n;
|
||||||
|
struct node *n1, *n2;
|
||||||
|
|
||||||
|
/* Create nodes on demand */
|
||||||
|
n1 = get_node(rstate, id1);
|
||||||
|
if (!n1)
|
||||||
|
n1 = new_node(rstate, id1);
|
||||||
|
n2 = get_node(rstate, id2);
|
||||||
|
if (!n2)
|
||||||
|
n2 = new_node(rstate, id2);
|
||||||
|
|
||||||
chan->scid = *scid;
|
chan->scid = *scid;
|
||||||
chan->connections[0] = chan->connections[1] = NULL;
|
|
||||||
chan->nodes[n1idx] = n1;
|
chan->nodes[n1idx] = n1;
|
||||||
chan->nodes[!n1idx] = n2;
|
chan->nodes[!n1idx] = n2;
|
||||||
chan->txout_script = NULL;
|
chan->txout_script = NULL;
|
||||||
@@ -315,52 +284,16 @@ static struct routing_channel *new_routing_channel(struct routing_state *rstate,
|
|||||||
tal_resize(&n1->channels, n+1);
|
tal_resize(&n1->channels, n+1);
|
||||||
n1->channels[n] = chan;
|
n1->channels[n] = chan;
|
||||||
|
|
||||||
|
/* Populate with (inactive) connections */
|
||||||
|
new_node_connection(rstate, chan, n1, n2, n1idx);
|
||||||
|
new_node_connection(rstate, chan, n2, n1, !n1idx);
|
||||||
|
|
||||||
uintmap_add(&rstate->channels, scid->u64, chan);
|
uintmap_add(&rstate->channels, scid->u64, chan);
|
||||||
|
|
||||||
tal_add_destructor2(chan, destroy_routing_channel, rstate);
|
tal_add_destructor2(chan, destroy_routing_channel, rstate);
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_connection *half_add_connection(struct routing_state *rstate,
|
|
||||||
const struct pubkey *from_id,
|
|
||||||
const struct pubkey *to_id,
|
|
||||||
const struct short_channel_id *scid)
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
struct node *from, *to;
|
|
||||||
struct routing_channel *chan;
|
|
||||||
struct node_connection *c;
|
|
||||||
|
|
||||||
from = get_node(rstate, from_id);
|
|
||||||
if (!from)
|
|
||||||
from = new_node(rstate, from_id);
|
|
||||||
to = get_node(rstate, to_id);
|
|
||||||
if (!to)
|
|
||||||
to = new_node(rstate, to_id);
|
|
||||||
|
|
||||||
/* FIXME: callers all have no channel? */
|
|
||||||
chan = find_channel(rstate, from, to, &idx);
|
|
||||||
if (!chan)
|
|
||||||
chan = new_routing_channel(rstate, scid, from, to);
|
|
||||||
|
|
||||||
c = chan->connections[idx];
|
|
||||||
if (!c) {
|
|
||||||
SUPERVERBOSE("Creating new route from %s to %s",
|
|
||||||
type_to_string(trc, struct pubkey, &from->id),
|
|
||||||
type_to_string(trc, struct pubkey, &to->id));
|
|
||||||
c = chan->connections[idx]
|
|
||||||
= new_node_connection(rstate, chan, from, to, idx);
|
|
||||||
} else {
|
|
||||||
status_trace("Updating existing route from %s to %s",
|
|
||||||
type_to_string(trc, struct pubkey, &from->id),
|
|
||||||
type_to_string(trc, struct pubkey, &to->id));
|
|
||||||
}
|
|
||||||
assert(c->src == from);
|
|
||||||
assert(c->dst == to);
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Too big to reach, but don't overflow if added. */
|
/* Too big to reach, but don't overflow if added. */
|
||||||
#define INFINITE 0x3FFFFFFFFFFFFFFFULL
|
#define INFINITE 0x3FFFFFFFFFFFFFFFULL
|
||||||
|
|
||||||
@@ -584,43 +517,6 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
|
|||||||
return first_conn;
|
return first_conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct node_connection *
|
|
||||||
add_channel_direction(struct routing_state *rstate, const struct pubkey *from,
|
|
||||||
const struct pubkey *to,
|
|
||||||
const struct short_channel_id *short_channel_id,
|
|
||||||
const u8 *announcement)
|
|
||||||
{
|
|
||||||
struct node_connection *c1, *c2, *c;
|
|
||||||
u16 direction = get_channel_direction(from, to);
|
|
||||||
|
|
||||||
c1 = get_connection(rstate, from, to);
|
|
||||||
c2 = get_connection_by_scid(rstate, short_channel_id, direction);
|
|
||||||
if(c2) {
|
|
||||||
/* We already know the channel by its scid, just
|
|
||||||
* update the announcement below */
|
|
||||||
c = c2;
|
|
||||||
} else if (c1) {
|
|
||||||
/* We found the channel by its endpoints, not by scid,
|
|
||||||
* so update its scid */
|
|
||||||
memcpy(&c1->short_channel_id, short_channel_id,
|
|
||||||
sizeof(c->short_channel_id));
|
|
||||||
c1->flags = direction;
|
|
||||||
c = c1;
|
|
||||||
} else {
|
|
||||||
/* We don't know this channel at all, create it */
|
|
||||||
c = half_add_connection(rstate, from, to, short_channel_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember the announcement so we can forward it to new peers */
|
|
||||||
if (announcement) {
|
|
||||||
tal_free(c->channel_announcement);
|
|
||||||
c->channel_announcement = tal_dup_arr(c, u8, announcement,
|
|
||||||
tal_count(announcement), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify the signature of a channel_update message */
|
/* Verify the signature of a channel_update message */
|
||||||
static bool check_channel_update(const struct pubkey *node_key,
|
static bool check_channel_update(const struct pubkey *node_key,
|
||||||
const secp256k1_ecdsa_signature *node_sig,
|
const secp256k1_ecdsa_signature *node_sig,
|
||||||
@@ -820,8 +716,7 @@ bool handle_pending_cannouncement(struct routing_state *rstate,
|
|||||||
const struct short_channel_id *scid,
|
const struct short_channel_id *scid,
|
||||||
const u8 *outscript)
|
const u8 *outscript)
|
||||||
{
|
{
|
||||||
bool forward, local;
|
bool local;
|
||||||
struct node_connection *c0, *c1;
|
|
||||||
u8 *tag;
|
u8 *tag;
|
||||||
const u8 *s;
|
const u8 *s;
|
||||||
struct pending_cannouncement *pending;
|
struct pending_cannouncement *pending;
|
||||||
@@ -868,30 +763,28 @@ bool handle_pending_cannouncement(struct routing_state *rstate,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this a new connection? It is if we don't know the
|
/* The channel may already exist if it was non-public from
|
||||||
* channel yet, or do not have a matching announcement in the
|
* local_add_channel(); normally we don't accept new
|
||||||
* case of side-loaded channels*/
|
* channel_announcements. See handle_channel_announcement. */
|
||||||
c0 = get_connection(rstate, &pending->node_id_2, &pending->node_id_1);
|
chan = get_channel(rstate, scid);
|
||||||
c1 = get_connection(rstate, &pending->node_id_1, &pending->node_id_2);
|
if (!chan)
|
||||||
forward = !c0 || !c1 || !c0->channel_announcement || !c1->channel_announcement;
|
chan = new_routing_channel(rstate, scid,
|
||||||
|
&pending->node_id_1,
|
||||||
SUPERVERBOSE("Announce for %s: %s<->%s: forward=%u c0=%p c1=%p c0->channel_announcement=%p c1->channel_announcement=%p",
|
&pending->node_id_2);
|
||||||
type_to_string(trc, struct short_channel_id, scid),
|
|
||||||
type_to_string(trc, struct pubkey, &pending->node_id_1),
|
|
||||||
type_to_string(trc, struct pubkey, &pending->node_id_2),
|
|
||||||
forward, c0, c1,
|
|
||||||
c0 ? c0->channel_announcement : NULL,
|
|
||||||
c1 ? c1->channel_announcement : NULL);
|
|
||||||
c0 = add_channel_direction(rstate, &pending->node_id_1, &pending->node_id_2,
|
|
||||||
&pending->short_channel_id, pending->announce);
|
|
||||||
c1 = add_channel_direction(rstate, &pending->node_id_2, &pending->node_id_1,
|
|
||||||
&pending->short_channel_id, pending->announce);
|
|
||||||
|
|
||||||
/* Channel is now public. */
|
/* Channel is now public. */
|
||||||
chan = get_channel(rstate, scid);
|
|
||||||
chan->public = true;
|
chan->public = true;
|
||||||
|
|
||||||
if (forward) {
|
/* Save channel_announcement. */
|
||||||
|
tal_free(chan->connections[0]->channel_announcement);
|
||||||
|
chan->connections[0]->channel_announcement
|
||||||
|
= tal_dup_arr(chan->connections[0], u8, pending->announce,
|
||||||
|
tal_len(pending->announce), 0);
|
||||||
|
tal_free(chan->connections[1]->channel_announcement);
|
||||||
|
chan->connections[1]->channel_announcement
|
||||||
|
= tal_dup_arr(chan->connections[1], u8, pending->announce,
|
||||||
|
tal_len(pending->announce), 0);
|
||||||
|
|
||||||
if (replace_broadcast(rstate->broadcasts,
|
if (replace_broadcast(rstate->broadcasts,
|
||||||
&chan->msg_indexes[MSG_INDEX_CANNOUNCE],
|
&chan->msg_indexes[MSG_INDEX_CANNOUNCE],
|
||||||
WIRE_CHANNEL_ANNOUNCEMENT,
|
WIRE_CHANNEL_ANNOUNCEMENT,
|
||||||
@@ -899,7 +792,6 @@ bool handle_pending_cannouncement(struct routing_state *rstate,
|
|||||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||||
"Announcement %s was replaced?",
|
"Announcement %s was replaced?",
|
||||||
tal_hex(trc, pending->announce));
|
tal_hex(trc, pending->announce));
|
||||||
}
|
|
||||||
|
|
||||||
local = pubkey_eq(&pending->node_id_1, &rstate->local_id) ||
|
local = pubkey_eq(&pending->node_id_1, &rstate->local_id) ||
|
||||||
pubkey_eq(&pending->node_id_2, &rstate->local_id);
|
pubkey_eq(&pending->node_id_2, &rstate->local_id);
|
||||||
@@ -914,7 +806,7 @@ bool handle_pending_cannouncement(struct routing_state *rstate,
|
|||||||
process_pending_node_announcement(rstate, &pending->node_id_2);
|
process_pending_node_announcement(rstate, &pending->node_id_2);
|
||||||
|
|
||||||
tal_free(pending);
|
tal_free(pending);
|
||||||
return local && forward;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_pending(struct pending_cannouncement *pending,
|
static void update_pending(struct pending_cannouncement *pending,
|
||||||
|
|||||||
@@ -178,13 +178,10 @@ struct routing_state *new_routing_state(const tal_t *ctx,
|
|||||||
const struct bitcoin_blkid *chain_hash,
|
const struct bitcoin_blkid *chain_hash,
|
||||||
const struct pubkey *local_id);
|
const struct pubkey *local_id);
|
||||||
|
|
||||||
/* Add a connection to the routing table, but do not mark it as usable
|
struct routing_channel *new_routing_channel(struct routing_state *rstate,
|
||||||
* yet. Used by channel_announcements before the channel_update comes
|
const struct short_channel_id *scid,
|
||||||
* in. */
|
const struct pubkey *id1,
|
||||||
struct node_connection *half_add_connection(struct routing_state *rstate,
|
const struct pubkey *id2);
|
||||||
const struct pubkey *from,
|
|
||||||
const struct pubkey *to,
|
|
||||||
const struct short_channel_id *scid);
|
|
||||||
|
|
||||||
/* Given a short_channel_id, retrieve the matching connection, or NULL if it is
|
/* Given a short_channel_id, retrieve the matching connection, or NULL if it is
|
||||||
* unknown. */
|
* unknown. */
|
||||||
|
|||||||
@@ -110,9 +110,14 @@ static struct node_connection *add_connection(struct routing_state *rstate,
|
|||||||
{
|
{
|
||||||
struct short_channel_id scid;
|
struct short_channel_id scid;
|
||||||
struct node_connection *c;
|
struct node_connection *c;
|
||||||
|
struct routing_channel *chan;
|
||||||
|
|
||||||
memset(&scid, 0, sizeof(scid));
|
memset(&scid, 0, sizeof(scid));
|
||||||
c = half_add_connection(rstate, from, to, &scid);
|
chan = get_channel(rstate, &scid);
|
||||||
|
if (!chan)
|
||||||
|
chan = new_routing_channel(rstate, &scid, from, to);
|
||||||
|
|
||||||
|
c = chan->connections[pubkey_idx(from, to)];
|
||||||
c->base_fee = base_fee;
|
c->base_fee = base_fee;
|
||||||
c->proportional_fee = proportional_fee;
|
c->proportional_fee = proportional_fee;
|
||||||
c->delay = delay;
|
c->delay = delay;
|
||||||
|
|||||||
@@ -75,9 +75,15 @@ get_or_make_connection(struct routing_state *rstate,
|
|||||||
const char *shortid)
|
const char *shortid)
|
||||||
{
|
{
|
||||||
struct short_channel_id scid;
|
struct short_channel_id scid;
|
||||||
|
struct routing_channel *chan;
|
||||||
|
|
||||||
if (!short_channel_id_from_str(shortid, strlen(shortid), &scid))
|
if (!short_channel_id_from_str(shortid, strlen(shortid), &scid))
|
||||||
abort();
|
abort();
|
||||||
return half_add_connection(rstate, from_id, to_id, &scid);
|
chan = get_channel(rstate, &scid);
|
||||||
|
if (!chan)
|
||||||
|
chan = new_routing_channel(rstate, &scid, from_id, to_id);
|
||||||
|
|
||||||
|
return chan->connections[pubkey_idx(from_id, to_id)];
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|||||||
@@ -72,9 +72,17 @@ static struct node_connection *add_connection(struct routing_state *rstate,
|
|||||||
{
|
{
|
||||||
struct short_channel_id scid;
|
struct short_channel_id scid;
|
||||||
struct node_connection *c;
|
struct node_connection *c;
|
||||||
|
struct routing_channel *chan;
|
||||||
|
|
||||||
memset(&scid, 0, sizeof(scid));
|
/* Make a unique scid. */
|
||||||
c = half_add_connection(rstate, from, to, &scid);
|
memcpy(&scid, from, sizeof(scid) / 2);
|
||||||
|
memcpy((char *)&scid + sizeof(scid) / 2, to, sizeof(scid) / 2);
|
||||||
|
|
||||||
|
chan = get_channel(rstate, &scid);
|
||||||
|
if (!chan)
|
||||||
|
chan = new_routing_channel(rstate, &scid, from, to);
|
||||||
|
|
||||||
|
c = chan->connections[pubkey_idx(from, to)];
|
||||||
c->base_fee = base_fee;
|
c->base_fee = base_fee;
|
||||||
c->proportional_fee = proportional_fee;
|
c->proportional_fee = proportional_fee;
|
||||||
c->delay = delay;
|
c->delay = delay;
|
||||||
@@ -84,6 +92,44 @@ static struct node_connection *add_connection(struct routing_state *rstate,
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns routing_channel connecting from and to: *idx set to refer
|
||||||
|
* to connection with src=from, dst=to */
|
||||||
|
static struct routing_channel *find_channel(struct routing_state *rstate,
|
||||||
|
const struct node *from,
|
||||||
|
const struct node *to,
|
||||||
|
int *idx)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
*idx = pubkey_idx(&from->id, &to->id);
|
||||||
|
|
||||||
|
n = tal_count(to->channels);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (to->channels[i]->nodes[*idx] == from)
|
||||||
|
return to->channels[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node_connection *get_connection(struct routing_state *rstate,
|
||||||
|
const struct pubkey *from_id,
|
||||||
|
const struct pubkey *to_id)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
struct node *from, *to;
|
||||||
|
struct routing_channel *c;
|
||||||
|
|
||||||
|
from = get_node(rstate, from_id);
|
||||||
|
to = get_node(rstate, to_id);
|
||||||
|
if (!from || ! to)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
c = find_channel(rstate, from, to, &idx);
|
||||||
|
if (!c)
|
||||||
|
return NULL;
|
||||||
|
return c->connections[idx];
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
static const struct bitcoin_blkid zerohash;
|
static const struct bitcoin_blkid zerohash;
|
||||||
|
|||||||
Reference in New Issue
Block a user