mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
gossmap: change local API.
Now we create a separate set of local mods, and apply and unapply it. This is more efficient than the previous approach, since we can do some work up-front. It's also more graceful (and well-defined) when a local modification overlaps an existing one. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
1490ae4cf6
commit
c5bd518d2f
415
common/gossmap.c
415
common/gossmap.c
@ -81,8 +81,8 @@ struct gossmap {
|
||||
/* Linked list of freed ones, if any. */
|
||||
u32 freed_nodes, freed_chans;
|
||||
|
||||
/* local messages (tal array) */
|
||||
u8 *local;
|
||||
/* local messages, if any. */
|
||||
const u8 *local;
|
||||
};
|
||||
|
||||
/* Accessors for the gossmap */
|
||||
@ -395,7 +395,8 @@ void gossmap_remove_node(struct gossmap *map, struct gossmap_node *node)
|
||||
* * [`point`:`node_id_1`]
|
||||
* * [`point`:`node_id_2`]
|
||||
*/
|
||||
static void add_channel(struct gossmap *map, size_t cannounce_off)
|
||||
static struct gossmap_chan *add_channel(struct gossmap *map,
|
||||
size_t cannounce_off)
|
||||
{
|
||||
/* Note that first two bytes are message type */
|
||||
const size_t feature_len_off = 2 + (64 + 64 + 64 + 64);
|
||||
@ -403,6 +404,7 @@ static void add_channel(struct gossmap *map, size_t cannounce_off)
|
||||
size_t scid_off;
|
||||
struct node_id node_id[2];
|
||||
struct gossmap_node *n[2];
|
||||
struct gossmap_chan *chan;
|
||||
u32 nidx[2];
|
||||
|
||||
feature_len = map_be16(map, cannounce_off + feature_len_off);
|
||||
@ -424,7 +426,7 @@ static void add_channel(struct gossmap *map, size_t cannounce_off)
|
||||
else
|
||||
nidx[1] = new_node(map);
|
||||
|
||||
new_channel(map, cannounce_off, scid_off, nidx[0], nidx[1]);
|
||||
chan = new_channel(map, cannounce_off, scid_off, nidx[0], nidx[1]);
|
||||
|
||||
/* Now we have a channel, we can add nodes to htable */
|
||||
if (!n[0])
|
||||
@ -433,6 +435,8 @@ static void add_channel(struct gossmap *map, size_t cannounce_off)
|
||||
if (!n[1])
|
||||
nodeidx_htable_add(&map->nodes,
|
||||
node2ptrint(map->node_arr + nidx[1]));
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
/* BOLT #7:
|
||||
@ -612,13 +616,11 @@ static bool load_gossip_store(struct gossmap *map)
|
||||
if (map->fd < 0)
|
||||
return false;
|
||||
|
||||
/* Start with empty local map */
|
||||
map->local = tal_arr(map, u8, 0);
|
||||
|
||||
fstat(map->fd, &st);
|
||||
map->st_dev = st.st_dev;
|
||||
map->st_ino = st.st_ino;
|
||||
map->map_size = st.st_size;
|
||||
map->local = NULL;
|
||||
/* If this fails, we fall back to read */
|
||||
map->mmap = mmap(NULL, map->map_size, PROT_READ, MAP_SHARED, map->fd, 0);
|
||||
if (map->mmap == MAP_FAILED)
|
||||
@ -661,69 +663,235 @@ static void destroy_map(struct gossmap *map)
|
||||
free(map->node_arr[i].chan_idxs);
|
||||
}
|
||||
|
||||
void gossmap_local_cleanup(struct gossmap *map)
|
||||
/* Local modifications. We only expect a few, so we use a simple
|
||||
* array. */
|
||||
struct localmod {
|
||||
struct short_channel_id scid;
|
||||
/* If this is an entirely-local channel, here's its offset.
|
||||
* Otherwise, 0xFFFFFFFF. */
|
||||
u32 local_off;
|
||||
|
||||
/* Are updates in either direction set? */
|
||||
bool updates_set[2];
|
||||
/* hc[n] defined if updates_set[n]. */
|
||||
struct half_chan hc[2];
|
||||
/* orig[n] defined if updates_set[n] and local_off == 0xFFFFFFFF */
|
||||
struct half_chan orig[2];
|
||||
};
|
||||
|
||||
struct gossmap_localmods {
|
||||
struct localmod *mods;
|
||||
/* This is the local array to be used by the gossmap */
|
||||
u8 *local;
|
||||
};
|
||||
|
||||
struct gossmap_localmods *gossmap_localmods_new(const tal_t *ctx)
|
||||
{
|
||||
size_t off, msglen;
|
||||
struct gossmap_localmods *localmods;
|
||||
|
||||
/* We need to undo all the local additions and updates.
|
||||
* FIXME: local updates may have overriden previous ones, but
|
||||
* we simply mark them disabled (they're usually used to
|
||||
* update local-only channels anyway). */
|
||||
for (off = 0;
|
||||
off < tal_bytelen(map->local);
|
||||
off += sizeof(msglen) + msglen) {
|
||||
struct short_channel_id scid;
|
||||
struct gossmap_chan *chan;
|
||||
be64 bescid;
|
||||
be16 type;
|
||||
localmods = tal(ctx, struct gossmap_localmods);
|
||||
localmods->mods = tal_arr(localmods, struct localmod, 0);
|
||||
localmods->local = tal_arr(localmods, u8, 0);
|
||||
|
||||
/* Local cursor */
|
||||
u8 *p = map->local + off;
|
||||
memcpy(&msglen, p, sizeof(msglen));
|
||||
p += sizeof(msglen);
|
||||
memcpy(&type, p, sizeof(type));
|
||||
p += sizeof(type);
|
||||
return localmods;
|
||||
}
|
||||
|
||||
if (type == CPU_TO_BE16(WIRE_CHANNEL_ANNOUNCEMENT)) {
|
||||
/* Get scid from inside announcement. */
|
||||
be16 flen;
|
||||
p += 64 * 4;
|
||||
memcpy(&flen, p, sizeof(flen));
|
||||
p += sizeof(flen) + be16_to_cpu(flen) + 32;
|
||||
memcpy(&bescid, p, sizeof(bescid));
|
||||
scid.u64 = be64_to_cpu(bescid);
|
||||
/* Create space at end of local map, return offset it was added at. */
|
||||
static size_t insert_local_space(struct gossmap_localmods *localmods,
|
||||
size_t msglen)
|
||||
{
|
||||
size_t oldlen = tal_bytelen(localmods->local);
|
||||
|
||||
chan = gossmap_find_chan(map, &scid);
|
||||
if (chan)
|
||||
gossmap_remove_chan(map, chan);
|
||||
} else {
|
||||
u8 channel_flags;
|
||||
assert(type == CPU_TO_BE16(WIRE_CHANNEL_UPDATE));
|
||||
p += 64 + 32;
|
||||
memcpy(&bescid, p, sizeof(bescid));
|
||||
p += sizeof(bescid);
|
||||
scid.u64 = be64_to_cpu(bescid);
|
||||
p += 4 + 1;
|
||||
channel_flags = *p;
|
||||
tal_resize(&localmods->local, oldlen + msglen);
|
||||
return oldlen;
|
||||
}
|
||||
|
||||
chan = gossmap_find_chan(map, &scid);
|
||||
/* May have removed it when we processed
|
||||
* announce above */
|
||||
if (chan)
|
||||
chan->half[channel_flags & 1].enabled = false;
|
||||
}
|
||||
static struct localmod *find_localmod(struct gossmap_localmods *localmods,
|
||||
const struct short_channel_id *scid)
|
||||
{
|
||||
for (size_t i = 0; i < tal_count(localmods->mods); i++)
|
||||
if (short_channel_id_eq(&localmods->mods[i].scid, scid))
|
||||
return &localmods->mods[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool gossmap_local_addchan(struct gossmap_localmods *localmods,
|
||||
const struct node_id *n1,
|
||||
const struct node_id *n2,
|
||||
const struct short_channel_id *scid,
|
||||
const u8 *features)
|
||||
{
|
||||
be16 be16;
|
||||
be64 be64;
|
||||
size_t off;
|
||||
struct localmod mod;
|
||||
|
||||
/* Don't create duplicate channels. */
|
||||
if (find_localmod(localmods, scid))
|
||||
return false;
|
||||
|
||||
mod.scid = *scid;
|
||||
mod.updates_set[0] = mod.updates_set[1] = false;
|
||||
|
||||
/* We create fake local channel_announcement. */
|
||||
off = insert_local_space(localmods,
|
||||
2 + 64 * 4 + 2 + tal_bytelen(features)
|
||||
+ 32 + 8 + 33 + 33);
|
||||
mod.local_off = off;
|
||||
|
||||
/* Set type to be kosher. */
|
||||
be16 = CPU_TO_BE16(WIRE_CHANNEL_ANNOUNCEMENT);
|
||||
memcpy(localmods->local + off, &be16, sizeof(be16));
|
||||
off += sizeof(be16);
|
||||
|
||||
/* Skip sigs */
|
||||
off += 64 * 4;
|
||||
|
||||
/* Set length and features */
|
||||
be16 = cpu_to_be16(tal_bytelen(features));
|
||||
memcpy(localmods->local + off, &be16, sizeof(be16));
|
||||
off += sizeof(be16);
|
||||
memcpy(localmods->local + off, features, tal_bytelen(features));
|
||||
off += tal_bytelen(features);
|
||||
|
||||
/* Skip chain_hash */
|
||||
off += 32;
|
||||
|
||||
/* Set scid */
|
||||
be64 = be64_to_cpu(scid->u64);
|
||||
memcpy(localmods->local + off, &be64, sizeof(be64));
|
||||
off += sizeof(be64);
|
||||
|
||||
/* set node_ids */
|
||||
memcpy(localmods->local + off, n1->k, sizeof(n1->k));
|
||||
off += sizeof(n1->k);
|
||||
memcpy(localmods->local + off, n2->k, sizeof(n2->k));
|
||||
off += sizeof(n2->k);
|
||||
|
||||
assert(off == tal_bytelen(localmods->local));
|
||||
|
||||
tal_arr_expand(&localmods->mods, mod);
|
||||
return true;
|
||||
};
|
||||
|
||||
/* Insert a local-only channel_update. */
|
||||
bool gossmap_local_updatechan(struct gossmap_localmods *localmods,
|
||||
const struct short_channel_id *scid,
|
||||
struct amount_msat htlc_min,
|
||||
struct amount_msat htlc_max,
|
||||
u32 base_fee,
|
||||
u32 proportional_fee,
|
||||
u16 delay,
|
||||
bool enabled,
|
||||
int dir)
|
||||
{
|
||||
struct localmod *mod;
|
||||
|
||||
mod = find_localmod(localmods, scid);
|
||||
if (!mod) {
|
||||
/* Create new reference to (presumably) existing channel. */
|
||||
size_t nmods = tal_count(localmods->mods);
|
||||
|
||||
tal_resize(&localmods->mods, nmods + 1);
|
||||
mod = &localmods->mods[nmods];
|
||||
mod->scid = *scid;
|
||||
mod->updates_set[0] = mod->updates_set[1] = false;
|
||||
mod->local_off = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Now zero out map */
|
||||
tal_resize(&map->local, 0);
|
||||
assert(dir == 0 || dir == 1);
|
||||
mod->updates_set[dir] = true;
|
||||
mod->hc[dir].enabled = enabled;
|
||||
/* node_idx needs to be set once we're in the gossmap. */
|
||||
mod->hc[dir].htlc_min
|
||||
= u64_to_fp16(htlc_min.millisatoshis, /* Raw: to fp16 */
|
||||
false);
|
||||
mod->hc[dir].htlc_max
|
||||
= u64_to_fp16(htlc_max.millisatoshis, /* Raw: to fp16 */
|
||||
true);
|
||||
mod->hc[dir].base_fee = base_fee;
|
||||
mod->hc[dir].proportional_fee = proportional_fee;
|
||||
mod->hc[dir].delay = delay;
|
||||
|
||||
/* Check they fit */
|
||||
if (mod->hc[dir].base_fee != base_fee
|
||||
|| mod->hc[dir].proportional_fee != proportional_fee
|
||||
|| mod->hc[dir].delay != delay)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Apply localmods to this map */
|
||||
void gossmap_apply_localmods(struct gossmap *map,
|
||||
struct gossmap_localmods *localmods)
|
||||
{
|
||||
size_t n = tal_count(localmods->mods);
|
||||
|
||||
assert(!map->local);
|
||||
map->local = localmods->local;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
struct localmod *mod = &localmods->mods[i];
|
||||
struct gossmap_chan *chan;
|
||||
|
||||
/* Find gossmap entry which this applies to. */
|
||||
chan = gossmap_find_chan(map, &mod->scid);
|
||||
/* If it doesn't exist, are we supposed to create a local one? */
|
||||
if (!chan) {
|
||||
if (mod->local_off == 0xFFFFFFFF)
|
||||
continue;
|
||||
|
||||
/* Create new channel, pointing into local. */
|
||||
chan = add_channel(map, map->map_size + mod->local_off);
|
||||
}
|
||||
|
||||
/* Save old, overwrite (keep nodeidx) */
|
||||
for (size_t h = 0; h < 2; h++) {
|
||||
if (!mod->updates_set[h])
|
||||
continue;
|
||||
mod->orig[h] = chan->half[h];
|
||||
chan->half[h] = mod->hc[h];
|
||||
chan->half[h].nodeidx = mod->orig[h].nodeidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gossmap_remove_localmods(struct gossmap *map,
|
||||
const struct gossmap_localmods *localmods)
|
||||
{
|
||||
size_t n = tal_count(localmods->mods);
|
||||
|
||||
assert(map->local == localmods->local);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const struct localmod *mod = &localmods->mods[i];
|
||||
struct gossmap_chan *chan = gossmap_find_chan(map, &mod->scid);
|
||||
|
||||
/* If that's a local channel, remove it now. */
|
||||
if (chan->cann_off >= map->map_size) {
|
||||
gossmap_remove_chan(map, chan);
|
||||
} else {
|
||||
/* Restore (keep nodeidx). */
|
||||
for (size_t h = 0; h < 2; h++) {
|
||||
u32 nodeidx;
|
||||
if (!mod->updates_set[h])
|
||||
continue;
|
||||
|
||||
nodeidx = chan->half[h].nodeidx;
|
||||
chan->half[h] = mod->orig[h];
|
||||
chan->half[h].nodeidx = nodeidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
map->local = NULL;
|
||||
}
|
||||
|
||||
bool gossmap_refresh(struct gossmap *map)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* You must clean local updates before this. */
|
||||
assert(tal_bytelen(map->local) == 0);
|
||||
/* You must remoe local updates before this. */
|
||||
assert(!map->local);
|
||||
|
||||
/* If file has changed, move to it. */
|
||||
if (stat(map->fname, &st) != 0)
|
||||
@ -762,141 +930,6 @@ struct gossmap *gossmap_load(const tal_t *ctx, const char *filename)
|
||||
return map;
|
||||
}
|
||||
|
||||
/* Add something to the local map, return offset it was added at. */
|
||||
static size_t insert_local_goss(struct gossmap *map, const u8 *msg TAKES)
|
||||
{
|
||||
size_t oldlen = tal_bytelen(map->local);
|
||||
size_t msglen = tal_bytelen(msg);
|
||||
|
||||
/* We store length, then the msg. */
|
||||
tal_resize(&map->local, oldlen + sizeof(msglen) + msglen);
|
||||
memcpy(map->local + oldlen, &msglen, sizeof(msglen));
|
||||
memcpy(map->local + oldlen + sizeof(msglen), msg, msglen);
|
||||
if (taken(msg))
|
||||
tal_free(msg);
|
||||
|
||||
return map->map_size + oldlen + sizeof(msglen);
|
||||
}
|
||||
|
||||
void gossmap_local_addchan(struct gossmap *map,
|
||||
const struct node_id *n1,
|
||||
const struct node_id *n2,
|
||||
const struct short_channel_id *scid,
|
||||
const u8 *features)
|
||||
{
|
||||
be16 be16;
|
||||
be64 be64;
|
||||
size_t off;
|
||||
u8 *fake_ann = tal_arr(NULL, u8,
|
||||
2 + 64 * 4 + 2 + tal_bytelen(features)
|
||||
+ 32 + 8 + 33 + 33);
|
||||
off = 0;
|
||||
|
||||
/* Set type to be kosher. */
|
||||
be16 = CPU_TO_BE16(WIRE_CHANNEL_ANNOUNCEMENT);
|
||||
memcpy(fake_ann + off, &be16, sizeof(be16));
|
||||
off += sizeof(be16);
|
||||
|
||||
/* Skip sigs */
|
||||
off += 64 * 4;
|
||||
|
||||
/* Set length and features */
|
||||
be16 = cpu_to_be16(tal_bytelen(features));
|
||||
memcpy(fake_ann + off, &be16, sizeof(be16));
|
||||
off += sizeof(be16);
|
||||
memcpy(fake_ann + off, features, tal_bytelen(features));
|
||||
off += tal_bytelen(features);
|
||||
|
||||
/* Skip chain_hash */
|
||||
off += 32;
|
||||
|
||||
/* Set scid */
|
||||
be64 = be64_to_cpu(scid->u64);
|
||||
memcpy(fake_ann + off, &be64, sizeof(be64));
|
||||
off += sizeof(be64);
|
||||
|
||||
/* set node_ids */
|
||||
memcpy(fake_ann + off, n1->k, sizeof(n1->k));
|
||||
off += sizeof(n1->k);
|
||||
memcpy(fake_ann + off, n2->k, sizeof(n2->k));
|
||||
off += sizeof(n2->k);
|
||||
|
||||
assert(off == tal_bytelen(fake_ann));
|
||||
|
||||
add_channel(map, insert_local_goss(map, take(fake_ann)));
|
||||
}
|
||||
|
||||
/* Insert a local-only channel_update (not in the mmap'ed gossmap,
|
||||
* cleared on refresh). Must exist! */
|
||||
void gossmap_local_updatechan(struct gossmap *map,
|
||||
const struct short_channel_id *scid,
|
||||
struct amount_msat htlc_min,
|
||||
struct amount_msat htlc_max,
|
||||
u32 base_fee,
|
||||
u32 proportional_fee,
|
||||
u16 delay,
|
||||
bool enabled,
|
||||
int dir)
|
||||
{
|
||||
be16 be16;
|
||||
be32 be32;
|
||||
be64 be64;
|
||||
size_t off;
|
||||
u8 *fake_upd = tal_arr(NULL, u8,
|
||||
2 + 64 + 32 + 8 + 4 + 1 + 1 + 2 + 8 + 4 + 4 + 8);
|
||||
|
||||
off = 0;
|
||||
|
||||
/* Set type to be kosher. */
|
||||
be16 = CPU_TO_BE16(WIRE_CHANNEL_UPDATE);
|
||||
memcpy(fake_upd + off, &be16, sizeof(be16));
|
||||
off += sizeof(be16);
|
||||
|
||||
/* Skip signature and chainhash */
|
||||
off += 64 + 32;
|
||||
|
||||
/* Set scid */
|
||||
be64 = be64_to_cpu(scid->u64);
|
||||
memcpy(fake_upd + off, &be64, sizeof(be64));
|
||||
off += sizeof(be64);
|
||||
|
||||
/* Skip timestamp. */
|
||||
off += 4;
|
||||
|
||||
/* We support htlc_maximum_msat. */
|
||||
fake_upd[off] = 1;
|
||||
off += 1;
|
||||
|
||||
/* Bottom bit is direction, second is disable. */
|
||||
fake_upd[off] = dir;
|
||||
if (!enabled)
|
||||
fake_upd[off] |= 2;
|
||||
off += 1;
|
||||
|
||||
be16 = cpu_to_be16(delay);
|
||||
memcpy(fake_upd + off, &be16, sizeof(be16));
|
||||
off += sizeof(be16);
|
||||
|
||||
be64 = cpu_to_be64(htlc_min.millisatoshis); /* Raw: endian */
|
||||
memcpy(fake_upd + off, &be64, sizeof(be64));
|
||||
off += sizeof(be64);
|
||||
|
||||
be32 = cpu_to_be32(base_fee);
|
||||
memcpy(fake_upd + off, &be32, sizeof(be32));
|
||||
off += sizeof(be32);
|
||||
|
||||
be32 = cpu_to_be32(proportional_fee);
|
||||
memcpy(fake_upd + off, &be32, sizeof(be32));
|
||||
off += sizeof(be32);
|
||||
|
||||
be64 = cpu_to_be64(htlc_max.millisatoshis); /* Raw: endian */
|
||||
memcpy(fake_upd + off, &be64, sizeof(be64));
|
||||
off += sizeof(be64);
|
||||
|
||||
assert(off == tal_bytelen(fake_upd));
|
||||
update_channel(map, insert_local_goss(map, take(fake_upd)));
|
||||
}
|
||||
|
||||
void gossmap_node_get_id(const struct gossmap *map,
|
||||
const struct gossmap_node *node,
|
||||
struct node_id *id)
|
||||
|
@ -43,20 +43,24 @@ struct gossmap *gossmap_load(const tal_t *ctx, const char *filename);
|
||||
* was updated. Note: this can scramble node and chan indexes! */
|
||||
bool gossmap_refresh(struct gossmap *map);
|
||||
|
||||
/* Insert a local-only channel (not in the mmap'ed gossmap, cleared on
|
||||
* refresh). */
|
||||
void gossmap_local_addchan(struct gossmap *map,
|
||||
/* Local modifications. */
|
||||
struct gossmap_localmods *gossmap_localmods_new(const tal_t *ctx);
|
||||
|
||||
/* Create a local-only channel; if this conflicts with a real channel when added,
|
||||
* that will be used instead.
|
||||
* Returns false (and does nothing) if scid was already in localmods.
|
||||
*/
|
||||
bool gossmap_local_addchan(struct gossmap_localmods *localmods,
|
||||
const struct node_id *n1,
|
||||
const struct node_id *n2,
|
||||
const struct short_channel_id *scid,
|
||||
const u8 *features)
|
||||
NON_NULL_ARGS(1,2,3,4);
|
||||
|
||||
/* Insert a local-only channel_update (not in the mmap'ed gossmap,
|
||||
* cleared on refresh). Must exist, and usually should be a local
|
||||
* channel (otherwise channel will be disabled on
|
||||
* gossmap_local_addchan!) */
|
||||
void gossmap_local_updatechan(struct gossmap *map,
|
||||
/* Create a local-only channel_update: can apply to lcoal-only or
|
||||
* normal channels. Returns false if amounts don't fit in our
|
||||
* internal representation (implies channel unusable anyway). */
|
||||
bool gossmap_local_updatechan(struct gossmap_localmods *localmods,
|
||||
const struct short_channel_id *scid,
|
||||
struct amount_msat htlc_min,
|
||||
struct amount_msat htlc_max,
|
||||
@ -67,9 +71,13 @@ void gossmap_local_updatechan(struct gossmap *map,
|
||||
int dir)
|
||||
NO_NULL_ARGS;
|
||||
|
||||
/* Remove all local-only changes. Must be done before calling
|
||||
* gossmap_refresh! */
|
||||
void gossmap_local_cleanup(struct gossmap *map);
|
||||
/* Apply localmods to this map */
|
||||
void gossmap_apply_localmods(struct gossmap *map,
|
||||
struct gossmap_localmods *localmods);
|
||||
|
||||
/* Remove localmods from this map */
|
||||
void gossmap_remove_localmods(struct gossmap *map,
|
||||
const struct gossmap_localmods *localmods);
|
||||
|
||||
/* Each channel has a unique (low) index. */
|
||||
u32 gossmap_node_idx(const struct gossmap *map, const struct gossmap_node *node);
|
||||
|
@ -334,6 +334,7 @@ int main(int argc, char *argv[])
|
||||
struct node_id l1, l2, l3, l4;
|
||||
struct short_channel_id scid23, scid12, scid_local;
|
||||
struct gossmap_chan *chan;
|
||||
struct gossmap_localmods *mods;
|
||||
|
||||
common_setup(argv[0]);
|
||||
|
||||
@ -358,11 +359,14 @@ int main(int argc, char *argv[])
|
||||
assert(gossmap_find_chan(map, &scid12));
|
||||
|
||||
/* Now, let's add a new channel l1 -> l4. */
|
||||
mods = gossmap_localmods_new(tmpctx);
|
||||
assert(node_id_from_hexstr("0382ce59ebf18be7d84677c2e35f23294b9992ceca95491fcf8a56c6cb2d9de199", 66, &l4));
|
||||
|
||||
assert(short_channel_id_from_str("111x1x1", 7, &scid_local));
|
||||
gossmap_local_addchan(map, &l1, &l4, &scid_local, NULL);
|
||||
|
||||
assert(gossmap_local_addchan(mods, &l1, &l4, &scid_local, NULL));
|
||||
|
||||
/* Apply changes, check they work. */
|
||||
gossmap_apply_localmods(map, mods);
|
||||
assert(gossmap_find_node(map, &l4));
|
||||
chan = gossmap_find_chan(map, &scid_local);
|
||||
|
||||
@ -370,11 +374,27 @@ int main(int argc, char *argv[])
|
||||
assert(!gossmap_chan_set(chan, 0));
|
||||
assert(!gossmap_chan_set(chan, 1));
|
||||
|
||||
/* Now update it. */
|
||||
gossmap_local_updatechan(map, &scid_local,
|
||||
/* Remove, no longer can find. */
|
||||
gossmap_remove_localmods(map, mods);
|
||||
|
||||
assert(!gossmap_find_chan(map, &scid_local));
|
||||
assert(!gossmap_find_node(map, &l4));
|
||||
|
||||
/* Now update it both local, and an existing one. */
|
||||
gossmap_local_updatechan(mods, &scid_local,
|
||||
AMOUNT_MSAT(1),
|
||||
AMOUNT_MSAT(100000),
|
||||
2, 3, 4, true, 0);
|
||||
|
||||
/* Adding an existing channel is a noop. */
|
||||
assert(gossmap_local_addchan(mods, &l2, &l3, &scid23, NULL));
|
||||
|
||||
gossmap_local_updatechan(mods, &scid23,
|
||||
AMOUNT_MSAT(99),
|
||||
AMOUNT_MSAT(100),
|
||||
101, 102, 103, true, 0);
|
||||
|
||||
gossmap_apply_localmods(map, mods);
|
||||
chan = gossmap_find_chan(map, &scid_local);
|
||||
assert(gossmap_chan_set(chan, 0));
|
||||
assert(!gossmap_chan_set(chan, 1));
|
||||
@ -386,8 +406,17 @@ int main(int argc, char *argv[])
|
||||
assert(chan->half[0].proportional_fee == 3);
|
||||
assert(chan->half[0].delay == 4);
|
||||
|
||||
chan = gossmap_find_chan(map, &scid23);
|
||||
assert(chan->half[0].enabled);
|
||||
assert(chan->half[0].htlc_min == u64_to_fp16(99, false));
|
||||
assert(chan->half[0].htlc_max == u64_to_fp16(100, true));
|
||||
assert(chan->half[0].base_fee == 101);
|
||||
assert(chan->half[0].proportional_fee == 102);
|
||||
assert(chan->half[0].delay == 103);
|
||||
|
||||
/* Cleanup leaves everything previous intact */
|
||||
gossmap_local_cleanup(map);
|
||||
gossmap_remove_localmods(map, mods);
|
||||
|
||||
assert(!gossmap_find_node(map, &l4));
|
||||
assert(!gossmap_find_chan(map, &scid_local));
|
||||
assert(gossmap_find_node(map, &l1));
|
||||
@ -396,6 +425,14 @@ int main(int argc, char *argv[])
|
||||
assert(gossmap_find_chan(map, &scid23));
|
||||
assert(gossmap_find_chan(map, &scid12));
|
||||
|
||||
chan = gossmap_find_chan(map, &scid23);
|
||||
assert(chan->half[0].enabled);
|
||||
assert(chan->half[0].htlc_min == u64_to_fp16(0, false));
|
||||
assert(chan->half[0].htlc_max == u64_to_fp16(990380000, true));
|
||||
assert(chan->half[0].base_fee == 20);
|
||||
assert(chan->half[0].proportional_fee == 1000);
|
||||
assert(chan->half[0].delay == 6);
|
||||
|
||||
/* Now we can refresh. */
|
||||
assert(write(fd, "", 1) == 1);
|
||||
gossmap_refresh(map);
|
||||
|
Loading…
Reference in New Issue
Block a user