mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 18:57:06 +01:00
gossipd: parse and respect optional htlc_maximum_msat
If another channel has set the optional `htlc_maximum_msat` field, we should correctly parse that field and respect it when drawing up routes for payments.
This commit is contained in:
parent
a3e87af19e
commit
b9331e5ac8
10 changed files with 77 additions and 18 deletions
2
Makefile
2
Makefile
|
@ -9,7 +9,7 @@ CCANDIR := ccan
|
|||
|
||||
# Where we keep the BOLT RFCs
|
||||
BOLTDIR := ../lightning-rfc/
|
||||
BOLTVERSION := 0891374d47ddffa64c5a2e6ad151247e3d6b7a59
|
||||
BOLTVERSION := b6ae60d24138a3601561fbc1c9d82d983595ae4f
|
||||
|
||||
-include config.vars
|
||||
|
||||
|
|
|
@ -23,6 +23,16 @@
|
|||
#define ROUTING_FLAGS_DIRECTION (1 << 0)
|
||||
#define ROUTING_FLAGS_DISABLED (1 << 1)
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* The `message_flags` bitfield is used to indicate the presence of optional
|
||||
* fields in the `channel_update` message:
|
||||
* | Bit Position | Name | Field |
|
||||
* | ------------- | ------------------------- | -------------------- |
|
||||
* | 0 | `option_channel_htlc_max` | `htlc_maximum_msat` |
|
||||
*/
|
||||
#define ROUTING_OPT_HTLC_MAX_MSAT (1 << 0)
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* - MUST NOT send `announcement_signatures` messages until `funding_locked`
|
||||
|
|
|
@ -361,6 +361,15 @@ static u64 risk_fee(u64 amount, u32 delay, double riskfactor)
|
|||
return 1 + amount * delay * riskfactor;
|
||||
}
|
||||
|
||||
/* Check that we can fit through this channel's indicated
|
||||
* maximum_ and minimum_msat requirements.
|
||||
*/
|
||||
static bool hc_can_carry(const struct half_chan *hc, u64 requiredcap)
|
||||
{
|
||||
return hc->htlc_maximum_msat >= requiredcap &&
|
||||
hc->htlc_minimum_msat <= requiredcap;
|
||||
}
|
||||
|
||||
/* We track totals, rather than costs. That's because the fee depends
|
||||
* on the current amount passing through. */
|
||||
static void bfg_one_edge(struct node *node,
|
||||
|
@ -398,13 +407,9 @@ static void bfg_one_edge(struct node *node,
|
|||
risk = node->bfg[h].risk +
|
||||
risk_fee(requiredcap, c->delay, riskfactor);
|
||||
|
||||
if (requiredcap > chan->satoshis * 1000) {
|
||||
/* Skip this edge if the channel has insufficient
|
||||
* capacity to route the required amount */
|
||||
continue;
|
||||
} else if (requiredcap < c->htlc_minimum_msat) {
|
||||
/* Skip a channels if it indicated that it won't route
|
||||
* the requeuested amount. */
|
||||
if (!hc_can_carry(c, requiredcap)) {
|
||||
/* Skip a channel if it indicated that it won't route
|
||||
* the requested amount. */
|
||||
continue;
|
||||
} else if (requiredcap >= MAX_MSATOSHI) {
|
||||
SUPERVERBOSE("...extreme %"PRIu64
|
||||
|
@ -1009,12 +1014,14 @@ static void set_connection_values(struct chan *chan,
|
|||
u8 message_flags,
|
||||
u8 channel_flags,
|
||||
u64 timestamp,
|
||||
u32 htlc_minimum_msat)
|
||||
u64 htlc_minimum_msat,
|
||||
u64 htlc_maximum_msat)
|
||||
{
|
||||
struct half_chan *c = &chan->half[idx];
|
||||
|
||||
c->delay = delay;
|
||||
c->htlc_minimum_msat = htlc_minimum_msat;
|
||||
c->htlc_maximum_msat = htlc_maximum_msat;
|
||||
c->base_fee = base_fee;
|
||||
c->proportional_fee = proportional_fee;
|
||||
c->message_flags = message_flags;
|
||||
|
@ -1051,15 +1058,17 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||
u64 htlc_minimum_msat;
|
||||
u32 fee_base_msat;
|
||||
u32 fee_proportional_millionths;
|
||||
u64 htlc_maximum_msat;
|
||||
struct bitcoin_blkid chain_hash;
|
||||
struct chan *chan;
|
||||
u8 direction;
|
||||
|
||||
if (!fromwire_channel_update(update, &signature, &chain_hash,
|
||||
if (!fromwire_channel_update_option_channel_htlc_max(update, &signature, &chain_hash,
|
||||
&short_channel_id, ×tamp,
|
||||
&message_flags, &channel_flags,
|
||||
&expiry, &htlc_minimum_msat, &fee_base_msat,
|
||||
&fee_proportional_millionths))
|
||||
&fee_proportional_millionths,
|
||||
&htlc_maximum_msat))
|
||||
return false;
|
||||
chan = get_channel(rstate, &short_channel_id);
|
||||
if (!chan)
|
||||
|
@ -1069,7 +1078,8 @@ bool routing_add_channel_update(struct routing_state *rstate,
|
|||
set_connection_values(chan, direction, fee_base_msat,
|
||||
fee_proportional_millionths, expiry,
|
||||
message_flags, channel_flags,
|
||||
timestamp, htlc_minimum_msat);
|
||||
timestamp, htlc_minimum_msat,
|
||||
htlc_maximum_msat);
|
||||
|
||||
/* Replace any old one. */
|
||||
tal_free(chan->half[direction].channel_update);
|
||||
|
|
|
@ -29,6 +29,9 @@ struct half_chan {
|
|||
/* Minimum number of msatoshi in an HTLC */
|
||||
u32 htlc_minimum_msat;
|
||||
|
||||
/* Maximum number of msatoshis in an HTLC */
|
||||
u64 htlc_maximum_msat;
|
||||
|
||||
/* Flags as specified by the `channel_update`s, among other
|
||||
* things indicated direction wrt the `channel_id` */
|
||||
u8 channel_flags;
|
||||
|
|
|
@ -65,6 +65,9 @@ bool fromwire_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNE
|
|||
/* Generated stub for fromwire_channel_update */
|
||||
bool fromwire_channel_update(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_channel_update_option_channel_htlc_max */
|
||||
bool fromwire_channel_update_option_channel_htlc_max(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, u64 *htlc_maximum_msat UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_update_option_channel_htlc_max called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_local_add_channel */
|
||||
bool fromwire_gossip_local_add_channel(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct pubkey *remote_node_id UNNEEDED, u64 *satoshis UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_local_add_channel called!\n"); abort(); }
|
||||
|
|
|
@ -29,6 +29,9 @@ bool fromwire_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNE
|
|||
/* Generated stub for fromwire_channel_update */
|
||||
bool fromwire_channel_update(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_channel_update_option_channel_htlc_max */
|
||||
bool fromwire_channel_update_option_channel_htlc_max(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, u64 *htlc_maximum_msat UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_update_option_channel_htlc_max called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_local_add_channel */
|
||||
bool fromwire_gossip_local_add_channel(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct pubkey *remote_node_id UNNEEDED, u64 *satoshis UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_local_add_channel called!\n"); abort(); }
|
||||
|
@ -126,8 +129,9 @@ get_or_make_connection(struct routing_state *rstate,
|
|||
/* Make sure it's seen as initialized (update non-NULL). */
|
||||
chan->half[idx].channel_update = (void *)chan;
|
||||
chan->half[idx].htlc_minimum_msat = 0;
|
||||
chan->half[idx].htlc_maximum_msat = satoshis * 1000;
|
||||
|
||||
return &chan->half[pubkey_idx(from_id, to_id)];
|
||||
return &chan->half[idx];
|
||||
}
|
||||
|
||||
static bool channel_is_between(const struct chan *chan,
|
||||
|
@ -151,7 +155,7 @@ int main(void)
|
|||
static const struct bitcoin_blkid zerohash;
|
||||
struct half_chan *nc;
|
||||
struct routing_state *rstate;
|
||||
struct pubkey a, b, c;
|
||||
struct pubkey a, b, c, d;
|
||||
u64 fee;
|
||||
struct chan **route;
|
||||
const double riskfactor = 1.0 / BLOCKS_PER_YEAR / 10000;
|
||||
|
@ -169,6 +173,9 @@ int main(void)
|
|||
pubkey_from_hexstr("02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06",
|
||||
strlen("02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06"),
|
||||
&c);
|
||||
pubkey_from_hexstr("02cca6c5c966fcf61d121e3a70e03a1cd9eeeea024b26ea666ce974d43b242e636",
|
||||
strlen("02cca6c5c966fcf61d121e3a70e03a1cd9eeeea024b26ea666ce974d43b242e636"),
|
||||
&d);
|
||||
|
||||
rstate = new_routing_state(tmpctx, &zerohash, &a, 0);
|
||||
|
||||
|
@ -226,11 +233,31 @@ int main(void)
|
|||
route = find_route(tmpctx, rstate, &a, &c, 999999, riskfactor, 0.0, NULL, &fee);
|
||||
assert(!route);
|
||||
|
||||
/* This should fail to returns a route because it is smaller than these
|
||||
/* This should fail to return a route because it is smaller than these
|
||||
* htlc_minimum_msat on the last channel. */
|
||||
route = find_route(tmpctx, rstate, &a, &c, 1, riskfactor, 0.0, NULL, &fee);
|
||||
assert(!route);
|
||||
|
||||
/* {'active': True, 'short_id': '6990:2:1/0', 'fee_per_kw': 10, 'delay': 5, 'message_flags': 1, 'htlc_maximum_msat': 500000, 'htlc_minimum_msat': 100, 'channel_flags': 0, 'destination': '02cca6c5c966fcf61d121e3a70e03a1cd9eeeea024b26ea666ce974d43b242e636', 'source': '03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf', 'last_update': 1504064344}, */
|
||||
nc = get_or_make_connection(rstate, &a, &d, "6991:2:1", 1000);
|
||||
nc->base_fee = 0;
|
||||
nc->proportional_fee = 0;
|
||||
nc->delay = 5;
|
||||
nc->channel_flags = 0;
|
||||
nc->message_flags = 1;
|
||||
nc->last_timestamp = 1504064344;
|
||||
nc->htlc_minimum_msat = 100;
|
||||
nc->htlc_maximum_msat = 500000; /* half capacity */
|
||||
|
||||
/* This should route correctly at the max_msat level */
|
||||
route = find_route(tmpctx, rstate, &a, &d, 500000, riskfactor, 0.0, NULL, &fee);
|
||||
assert(route);
|
||||
|
||||
/* This should fail to return a route because it's larger than the
|
||||
* htlc_maximum_msat on the last channel. */
|
||||
route = find_route(tmpctx, rstate, &a, &d, 500001, riskfactor, 0.0, NULL, &fee);
|
||||
assert(!route);
|
||||
|
||||
tal_free(tmpctx);
|
||||
secp256k1_context_destroy(secp256k1_ctx);
|
||||
return 0;
|
||||
|
|
|
@ -27,6 +27,9 @@ bool fromwire_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNE
|
|||
/* Generated stub for fromwire_channel_update */
|
||||
bool fromwire_channel_update(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_update called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_channel_update_option_channel_htlc_max */
|
||||
bool fromwire_channel_update_option_channel_htlc_max(const void *p UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct bitcoin_blkid *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u8 *message_flags UNNEEDED, u8 *channel_flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, u64 *htlc_maximum_msat UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_update_option_channel_htlc_max called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_local_add_channel */
|
||||
bool fromwire_gossip_local_add_channel(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct pubkey *remote_node_id UNNEEDED, u64 *satoshis UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_gossip_local_add_channel called!\n"); abort(); }
|
||||
|
@ -112,6 +115,7 @@ static void add_connection(struct routing_state *rstate,
|
|||
struct short_channel_id scid;
|
||||
struct half_chan *c;
|
||||
struct chan *chan;
|
||||
int satoshis = 100000;
|
||||
|
||||
/* Make a unique scid. */
|
||||
memcpy(&scid, from, sizeof(scid) / 2);
|
||||
|
@ -119,7 +123,7 @@ static void add_connection(struct routing_state *rstate,
|
|||
|
||||
chan = get_channel(rstate, &scid);
|
||||
if (!chan)
|
||||
chan = new_chan(rstate, &scid, from, to, 100000);
|
||||
chan = new_chan(rstate, &scid, from, to, satoshis);
|
||||
|
||||
c = &chan->half[pubkey_idx(from, to)];
|
||||
/* Make sure it's seen as initialized (update non-NULL). */
|
||||
|
@ -129,6 +133,7 @@ static void add_connection(struct routing_state *rstate,
|
|||
c->delay = delay;
|
||||
c->channel_flags = get_channel_direction(from, to);
|
||||
c->htlc_minimum_msat = 0;
|
||||
c->htlc_maximum_msat = satoshis * 1000;
|
||||
}
|
||||
|
||||
/* Returns chan connecting from and to: *idx set to refer
|
||||
|
|
|
@ -71,7 +71,7 @@ void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UN
|
|||
void fatal(const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "fatal called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_connect_peer_connected */
|
||||
bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED)
|
||||
bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **globalfeatures UNNEEDED, u8 **localfeatures UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_connect_peer_connected called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_get_incoming_channels_reply */
|
||||
bool fromwire_gossip_get_incoming_channels_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct route_info **route_info UNNEEDED)
|
||||
|
|
|
@ -83,7 +83,7 @@ bool fromwire_channel_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p
|
|||
bool fromwire_channel_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, u32 *feerate UNNEEDED, struct changed_htlc **changed UNNEEDED, secp256k1_ecdsa_signature *commit_sig UNNEEDED, secp256k1_ecdsa_signature **htlc_sigs UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_channel_sending_commitsig called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_connect_peer_connected */
|
||||
bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **gfeatures UNNEEDED, u8 **lfeatures UNNEEDED)
|
||||
bool fromwire_connect_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct crypto_state *crypto_state UNNEEDED, u8 **globalfeatures UNNEEDED, u8 **localfeatures UNNEEDED)
|
||||
{ fprintf(stderr, "fromwire_connect_peer_connected called!\n"); abort(); }
|
||||
/* Generated stub for fromwire_gossip_resolve_channel_reply */
|
||||
bool fromwire_gossip_resolve_channel_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey **keys UNNEEDED)
|
||||
|
|
|
@ -149,6 +149,7 @@ channel_update,110,cltv_expiry_delta,2
|
|||
channel_update,112,htlc_minimum_msat,8
|
||||
channel_update,120,fee_base_msat,4
|
||||
channel_update,124,fee_proportional_millionths,4
|
||||
channel_update,128,htlc_maximum_msat,8,option_channel_htlc_max
|
||||
query_short_channel_ids,261
|
||||
query_short_channel_ids,0,chain_hash,32
|
||||
query_short_channel_ids,32,len,2
|
||||
|
|
Loading…
Add table
Reference in a new issue