-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
invoicesrpc: specify private hops for addinvoice, addholdinvoice #3022
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In terms of commit structure, it may be better to just make two commits: one for lnd
and one for lncli
building off of that.
cli.StringFlag{ | ||
Name: "private_hops", | ||
Usage: "a json array string of private channel ids " + | ||
"to use as hop hints", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not the simpler format --private_hops 100,200,300
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Name: "private_hops", | ||
Usage: "a json array string of private channel ids " + | ||
"to use as hop hints", | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want, you can do some reuse here. See commands.go
, paymentFlags()
.
lnrpc/invoicesrpc/addinvoice.go
Outdated
// any channels not in the array. | ||
if len(invoice.PrivateHops) > 0 { | ||
match := false | ||
for _, privateChan := range invoice.PrivateHops { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be better to implement using a map[uint64]struct{}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, done
lnrpc/invoicesrpc/invoices.proto
Outdated
/** | ||
The list of private channel ids that will be used as hop hints. | ||
*/ | ||
repeated uint64 private_hops = 10 [json_name = "private_hops"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering whether name should be private_channels
? But we also have hop hints...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to private_channels
since I think it's more descriptive
Can you also give a bit more background on how exactly you'd be using this? Is the goal to only expose one private channel for every peer connected to, so that the invoice doesn't disclose the combined capacity of all channels to a peer? Or do you maybe have info on how the sender is going to approach you? |
Currently the commands include all private channels as hop hints by default. Users may not even know that this is happening (I didn't), so I disabled that in this PR. If I only wanted to specify one, or a few, for the sender to use in path finding, this gives me more granular control. Perhaps some of these private channels are unbalanced and could use some balancing. Maybe there is one "very secret" private channel that I don't want exposed via the regular add(hold)invoice command(s) and I don't really care if my other private channels get exposed to the sender. |
@joostjager I'm looking for this feature as well. My Internet connection comes with carrier-grade NAT, so simply setting NAT=true didn't seem to work. I have to embed routing hints of the channel counterparty to receive funds. Eclair mobile has done this properly, while LN-App still generates invoices without any routing hints, which cannot be paid. |
@andronoob Yes, for non-routing nodes you should be using private channels. |
@halseth In other words, it's a limitation of LN protocol that NAT can be a problem for routing nodes, therefore routing nodes must figure out how to overcome this problem by themselves, right? |
A routing node must be connectable, and how that is achieved is not a protocol problem.
So yes :) |
861cc07
to
c40e926
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice addition, thanks @Crypt-iQ!
Just a few nits/ UX questions from my side :)
@@ -82,6 +82,11 @@ message AddHoldInvoiceRequest { | |||
|
|||
/// Whether this invoice should include routing hints for private channels. | |||
bool private = 9 [json_name = "private"]; | |||
|
|||
/** | |||
The list of private channel ids that will be used as hop hints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: add that these are short channel IDs?
It's apparent from the uint64 when you're used to the rpc, but might be helpful for newer users :)
@@ -6,6 +6,7 @@ import ( | |||
"context" | |||
"encoding/hex" | |||
"fmt" | |||
"strings" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well blitz this unnecessary newline while you're here?
@@ -253,6 +258,16 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, | |||
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta))) | |||
} | |||
|
|||
if len(invoice.PrivateChannels) > 0 && !invoice.Private { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't the presence of a list of private channels imply that the user wants to have a private invoice?
Non-critical, but I can definitely see myself calling with a list of channels and forgetting the private flag and wanting it to be set anyway.
// the list of hop hints. | ||
sid := channel.ShortChannelID.ToUint64() | ||
if _, ok := privateChanMap[sid]; !ok { | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As is, users can provide public or already closed channels in this list and they will just be filtered out by this + the isPublic check, which could result in there being no hints added when the user gives bad input?
The extreme case would be to error if they provide hops and we end up using none, but maybe just add some logging along the lines of private invoice: received {len} suggested channels, created: {numHints} hints
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, agree
@@ -2242,6 +2242,11 @@ message Invoice { | |||
|
|||
/// List of HTLCs paying to this invoice [EXPERIMENTAL]. | |||
repeated InvoiceHTLC htlcs = 22 [json_name = "htlcs"]; | |||
|
|||
/** | |||
The list of private channel ids that will be used as hop hints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment that hop hints will be strictly limited to these channels if they are specified?
A potential workaround for this issue now exists with the signMessage RPC API, you can encode your own BOLT 11 payment request however you like and then use that API to craft the signature for the payment request |
I agree with this, but I think that might be complicated for new users? Also at a minimum I think the private hops should not be specified by default if possible |
Fixes #2963
This PR allows a user to manually specify private channels to be used as hop hints in both the
addinvoice
andaddholdinvoice
RPC calls via the new--private_hops
flag which accepts a JSON array of private channel ids. The new flag must be used in conjunction with the--private
flag. In the current implementation, users will advertise all private channels which isn't ideal for privacy-conscious users.I also changed the
--private
flag fromBoolTFlag
toBoolFlag
so that users aren't always leaking their private channels if they don't want to.Usage:
addinvoice
lncli addinvoice --private_hops '[467292441870336, 447501232570368, 487083651170304]' --private
addholdinvoice
lncli addholdinvoice <hash> --private_hops '[467292441870336, 447501232570368, 487083651170304]' --private