#include "config.h"
#include <plugins/renepay/renepayconfig.h>
#include <plugins/renepay/uncertainty.h>
void uncertainty_route_success(struct uncertainty *uncertainty,
const struct route *route)
{
if (!route->hops)
return;
for (size_t i = 0; i < tal_count(route->hops); i++) {
const struct route_hop *hop = &route->hops[i];
struct short_channel_id_dir scidd = {hop->scid, hop->direction};
chan_extra_sent_success(uncertainty->chan_extra_map, &scidd,
route->hops[i].amount);
}
}
void uncertainty_remove_htlcs(struct uncertainty *uncertainty,
const struct route *route)
{
if (!route->hops)
return;
const size_t pathlen = tal_count(route->hops);
for (size_t i = 0; i < pathlen; i++) {
const struct route_hop *hop = &route->hops[i];
struct short_channel_id_dir scidd = {hop->scid, hop->direction};
chan_extra_remove_htlc(uncertainty->chan_extra_map, &scidd,
hop->amount);
}
}
void uncertainty_commit_htlcs(struct uncertainty *uncertainty,
const struct route *route)
{
if (!route->hops)
return;
const size_t pathlen = tal_count(route->hops);
for (size_t i = 0; i < pathlen; i++) {
const struct route_hop *hop = &route->hops[i];
struct short_channel_id_dir scidd = {hop->scid, hop->direction};
chan_extra_commit_htlc(uncertainty->chan_extra_map, &scidd,
hop->amount);
}
}
void uncertainty_channel_can_send(struct uncertainty *uncertainty,
struct short_channel_id scid, int direction)
{
struct short_channel_id_dir scidd = {scid, direction};
chan_extra_can_send(uncertainty->chan_extra_map, &scidd);
}
void uncertainty_channel_cannot_send(struct uncertainty *uncertainty,
struct short_channel_id scid,
int direction)
{
struct short_channel_id_dir scidd = {scid, direction};
chan_extra_cannot_send(uncertainty->chan_extra_map, &scidd);
}
int uncertainty_update(struct uncertainty *uncertainty, struct gossmap *gossmap)
{
assert(uncertainty);
struct chan_extra_map *chan_extra_map = uncertainty->chan_extra_map;
assert(chan_extra_map);
struct chan_extra **del_list = tal_arr(NULL, struct chan_extra*, 0);
struct chan_extra_map_iter it;
for (struct chan_extra *ch = chan_extra_map_first(chan_extra_map, &it);
ch; ch = chan_extra_map_next(chan_extra_map, &it)) {
if (!gossmap_find_chan(gossmap, &ch->scid))
tal_arr_expand(&del_list, ch);
}
for(size_t i=0;i<tal_count(del_list);i++) {
chan_extra_map_del(chan_extra_map, del_list[i]);
del_list[i] = tal_free(del_list[i]);
}
del_list = tal_free(del_list);
int skipped_count = 0;
for (struct gossmap_chan *chan = gossmap_first_chan(gossmap); chan;
chan = gossmap_next_chan(gossmap, chan)) {
struct short_channel_id scid = gossmap_chan_scid(gossmap, chan);
struct chan_extra *ce =
chan_extra_map_get(chan_extra_map, scid);
if (!ce) {
struct amount_msat cap_msat;
cap_msat = gossmap_chan_get_capacity(gossmap, chan);
if (!new_chan_extra(chan_extra_map, scid,
cap_msat)) {
skipped_count++;
continue;
}
}
}
assert(chan_extra_map_count(chan_extra_map) + skipped_count ==
gossmap_num_chans(gossmap));
return skipped_count;
}
struct uncertainty *uncertainty_new(const tal_t *ctx)
{
struct uncertainty *uncertainty = tal(ctx, struct uncertainty);
if (uncertainty == NULL)
goto function_fail;
uncertainty->chan_extra_map = tal(uncertainty, struct chan_extra_map);
if (uncertainty->chan_extra_map == NULL)
goto function_fail;
chan_extra_map_init(uncertainty->chan_extra_map);
return uncertainty;
function_fail:
return tal_free(uncertainty);
}
struct chan_extra_map *
uncertainty_get_chan_extra_map(struct uncertainty *uncertainty)
{
return uncertainty->chan_extra_map;
}
struct chan_extra *
uncertainty_add_channel(struct uncertainty *uncertainty,
const struct short_channel_id scid,
struct amount_msat capacity)
{
struct chan_extra *ce =
chan_extra_map_get(uncertainty->chan_extra_map, scid);
if (ce)
return ce;
return new_chan_extra(uncertainty->chan_extra_map, scid, capacity);
}
bool uncertainty_set_liquidity(struct uncertainty *uncertainty,
const struct short_channel_id_dir *scidd,
struct amount_msat min,
struct amount_msat max)
{
enum renepay_errorcode err = chan_extra_set_liquidity(
uncertainty->chan_extra_map, scidd, min, max);
return err == RENEPAY_NOERROR;
}
struct chan_extra *uncertainty_find_channel(struct uncertainty *uncertainty,
const struct short_channel_id scid)
{
return chan_extra_map_get(uncertainty->chan_extra_map, scid);
}
enum renepay_errorcode uncertainty_relax(struct uncertainty *uncertainty,
double seconds)
{
assert(seconds >= 0);
const double fraction = MIN(seconds / TIMER_FORGET_SEC, 1.0);
struct chan_extra_map *chan_extra_map =
uncertainty_get_chan_extra_map(uncertainty);
struct chan_extra_map_iter it;
for (struct chan_extra *ce = chan_extra_map_first(chan_extra_map, &it);
ce; ce = chan_extra_map_next(chan_extra_map, &it)) {
enum renepay_errorcode err =
chan_extra_relax_fraction(ce, fraction);
if (err)
return err;
}
return RENEPAY_NOERROR;
}