diff --git a/lightningd/channel.c b/lightningd/channel.c index 49ea854d4..d0b90da19 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -601,15 +601,6 @@ struct channel_inflight *channel_inflight_find(struct channel *channel, return NULL; } -struct channel *active_channel_by_scid(struct lightningd *ld, - const struct short_channel_id *scid) -{ - struct channel *chan = any_channel_by_scid(ld, scid); - if (chan && !channel_active(chan)) - chan = NULL; - return chan; -} - struct channel *any_channel_by_scid(struct lightningd *ld, const struct short_channel_id *scid) { diff --git a/lightningd/channel.h b/lightningd/channel.h index 7c42752bf..db81ce8c4 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -394,8 +394,6 @@ struct channel *peer_any_unsaved_channel(struct peer *peer, bool *others); struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid); -struct channel *active_channel_by_scid(struct lightningd *ld, - const struct short_channel_id *scid); struct channel *any_channel_by_scid(struct lightningd *ld, const struct short_channel_id *scid); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 759f58208..fdedc84f5 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -546,7 +546,7 @@ static void subtract_received_htlcs(const struct channel *channel, } } -static struct amount_msat channel_amount_spendable(const struct channel *channel) +struct amount_msat channel_amount_spendable(const struct channel *channel) { struct amount_msat spendable; @@ -1770,14 +1770,18 @@ command_find_channel(struct command *cmd, tok->end - tok->start, buffer + tok->start); } else if (json_to_short_channel_id(buffer, tok, &scid)) { - *channel = active_channel_by_scid(ld, &scid); - if (*channel) - return NULL; - - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Short channel ID not found: '%.*s'", - tok->end - tok->start, - buffer + tok->start); + *channel = any_channel_by_scid(ld, &scid); + if (!*channel) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Short channel ID not found: '%.*s'", + tok->end - tok->start, + buffer + tok->start); + if (!channel_active(*channel)) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Short channel ID not active: '%.*s'", + tok->end - tok->start, + buffer + tok->start); + return NULL; } else { return command_fail_badparam(cmd, "id", buffer, tok, "should be a channel ID or short channel ID"); diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 4e3207609..77037e17d 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -92,6 +92,10 @@ void channel_watch_funding(struct lightningd *ld, struct channel *channel); /* If this channel has a "wrong funding" shutdown, watch that too. */ void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel); +/* How much can we spend in this channel? */ +struct amount_msat channel_amount_spendable(const struct channel *channel); + +/* How much can we receive in this channel? */ struct amount_msat channel_amount_receivable(const struct channel *channel); /* Pull peers, channels and HTLCs from db, and wire them up. diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index e0d902c71..7a434bbd3 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -621,11 +621,45 @@ static void forward_htlc(struct htlc_in *hin, { const u8 *failmsg; struct lightningd *ld = hin->key.channel->peer->ld; - struct channel *next = active_channel_by_scid(ld, scid); + struct channel *next; struct htlc_out *hout = NULL; + /* This is a shortcut for specifying next peer; doesn't mean + * the actual channel! */ + next = any_channel_by_scid(ld, scid); + if (next) { + struct peer *peer = next->peer; + struct channel *channel; + struct amount_msat best_spendable = channel_amount_spendable(next); + + /* Seek channel with largest spendable! */ + list_for_each(&peer->channels, channel, list) { + struct amount_msat spendable; + if (!channel_can_add_htlc(channel)) + continue; + spendable = channel_amount_spendable(channel); + if (!amount_msat_greater(spendable, best_spendable)) + continue; + + /* Don't override if fees differ... */ + if (channel->feerate_base != next->feerate_base + || channel->feerate_ppm != next->feerate_ppm) + continue; + /* Or if this would be below min for channel! */ + if (amount_msat_less(amt_to_forward, + channel->channel_info.their_config.htlc_minimum)) + continue; + + /* OK, it's better! */ + log_debug(next->log, "Chose a better channel: %s", + type_to_string(tmpctx, struct short_channel_id, + channel->scid)); + next = channel; + } + } + /* Unknown peer, or peer not ready. */ - if (!next || !next->scid) { + if (!next || !channel_active(next)) { local_fail_in_htlc(hin, take(towire_unknown_next_peer(NULL))); wallet_forwarded_payment_add(hin->key.channel->peer->ld->wallet, hin, next ? next->scid : NULL, NULL, diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index ec4c220d2..81e5c1bae 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -10,10 +10,10 @@ bool deprecated_apis = false; /* AUTOGENERATED MOCKS START */ -/* Generated stub for active_channel_by_scid */ -struct channel *active_channel_by_scid(struct lightningd *ld UNNEEDED, - const struct short_channel_id *scid UNNEEDED) -{ fprintf(stderr, "active_channel_by_scid called!\n"); abort(); } +/* Generated stub for any_channel_by_scid */ +struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED, + const struct short_channel_id *scid UNNEEDED) +{ fprintf(stderr, "any_channel_by_scid called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, diff --git a/tests/test_connection.py b/tests/test_connection.py index 5224c429c..0707c53ca 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -3784,11 +3784,11 @@ def test_multichan(node_factory, executor, bitcoind): scid12 = l1.get_channel_scid(l2) scid23a = l2.get_channel_scid(l3) - # Now fund *second* channel l2->l3. + # Now fund *second* channel l2->l3 (slightly larger) bitcoind.rpc.sendtoaddress(l2.rpc.newaddr()['bech32'], 0.1) bitcoind.generate_block(1) sync_blockheight(bitcoind, [l2]) - l2.rpc.fundchannel(l3.info['id'], '0.05btc') + l2.rpc.fundchannel(l3.info['id'], '0.01001btc') assert(len(only_one(l2.rpc.listpeers(l3.info['id'])['peers'])['channels']) == 2) assert(len(only_one(l3.rpc.listpeers(l2.info['id'])['peers'])['channels']) == 2) @@ -3830,9 +3830,9 @@ def test_multichan(node_factory, executor, bitcoind): chan23a_idx = 1 chan23b_idx = 0 - # Check it used the right scid! - assert before[chan23a_idx]['to_us_msat'] != after[chan23a_idx]['to_us_msat'] - assert before[chan23b_idx]['to_us_msat'] == after[chan23b_idx]['to_us_msat'] + # Check it used the larger channel! + assert before[chan23a_idx]['to_us_msat'] == after[chan23a_idx]['to_us_msat'] + assert before[chan23b_idx]['to_us_msat'] != after[chan23b_idx]['to_us_msat'] before = only_one(l2.rpc.listpeers(l3.info['id'])['peers'])['channels'] route[1]['channel'] = scid23b @@ -3843,9 +3843,9 @@ def test_multichan(node_factory, executor, bitcoind): wait_for(lambda: [c['htlcs'] for c in only_one(l2.rpc.listpeers(l3.info['id'])['peers'])['channels']] == [[], []]) after = only_one(l2.rpc.listpeers(l3.info['id'])['peers'])['channels'] - # Check it used the right scid! - assert before[chan23a_idx]['to_us_msat'] == after[chan23a_idx]['to_us_msat'] - assert before[chan23b_idx]['to_us_msat'] != after[chan23b_idx]['to_us_msat'] + # Now the first channel is larger! + assert before[chan23a_idx]['to_us_msat'] != after[chan23a_idx]['to_us_msat'] + assert before[chan23b_idx]['to_us_msat'] == after[chan23b_idx]['to_us_msat'] # Make sure gossip works. bitcoind.generate_block(5) @@ -3862,5 +3862,5 @@ def test_multichan(node_factory, executor, bitcoind): assert chan23a['amount_msat'] == Millisatoshi(1000000000) assert chan23a['short_channel_id'] == scid23a - assert chan23b['amount_msat'] == Millisatoshi(5000000000) + assert chan23b['amount_msat'] == Millisatoshi(1001000000) assert chan23b['short_channel_id'] == scid23b