diff --git a/Makefile b/Makefile index 2c3fe53be..df30067da 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ CCANDIR := ccan # Where we keep the BOLT RFCs BOLTDIR := ../lightning-rfc/ -BOLTVERSION := 0891374d47ddffa64c5a2e6ad151247e3d6b7a59 +BOLTVERSION := b6ae60d24138a3601561fbc1c9d82d983595ae4f -include config.vars diff --git a/gossipd/gossip_constants.h b/gossipd/gossip_constants.h index 4b1e0c040..77a3de5bd 100644 --- a/gossipd/gossip_constants.h +++ b/gossipd/gossip_constants.h @@ -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` diff --git a/gossipd/routing.c b/gossipd/routing.c index 52c63769f..df37ba2fb 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -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); diff --git a/gossipd/routing.h b/gossipd/routing.h index fe48b9b9f..4af8a4e5a 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -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; diff --git a/gossipd/test/run-bench-find_route.c b/gossipd/test/run-bench-find_route.c index 0347217c2..27d9b192a 100644 --- a/gossipd/test/run-bench-find_route.c +++ b/gossipd/test/run-bench-find_route.c @@ -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(); } diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index 90b8d7040..4f2c3ce79 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -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; diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index 88ed4660c..c3cc58434 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -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 diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 663182ce1..41f35a1a7 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -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) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 2e478bcc8..433d0c343 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -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) diff --git a/wire/gen_peer_wire_csv b/wire/gen_peer_wire_csv index 4afd7776f..7f00754cf 100644 --- a/wire/gen_peer_wire_csv +++ b/wire/gen_peer_wire_csv @@ -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