Skip to content
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

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lnrpc/invoicesrpc/addinvoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ type AddInvoiceData struct {
// Whether this invoice should include routing hints for private
// channels.
Private bool

// An optional array that may contain private channel ids to be used
// as hop hints. Privacy-conscious users may use this to select
// specific private channels rather than all of them.
PrivateChannels []uint64
}

// AddInvoice attempts to add a new invoice to the invoice database. Any
Expand Down Expand Up @@ -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 {
Copy link
Collaborator

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.

return nil, nil, fmt.Errorf("must set private flag in conjunction " +
"with privatechannels")
}

privateChanMap := make(map[uint64]struct{})
for _, privateChan := range invoice.PrivateChannels {
privateChanMap[privateChan] = struct{}{}
}

// If we were requested to include routing hints in the invoice, then
// we'll fetch all of our available private channels and create routing
// hints for them.
Expand All @@ -279,6 +294,18 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
continue
}

// If the user has manually defined private hop hints, ignore
// any channels not in the array.
if len(invoice.PrivateChannels) > 0 {
// Check to see whether the ShortChannelID exists in the private
// channel map. If it isn't, don't add this private channel to
// the list of hop hints.
sid := channel.ShortChannelID.ToUint64()
if _, ok := privateChanMap[sid]; !ok {
continue
Copy link
Collaborator

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?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, agree

}
}

// Make sure the counterparty has enough balance in the
// channel for our amount. We do this in order to reduce
// payment errors when attempting to use this channel
Expand Down
79 changes: 45 additions & 34 deletions lnrpc/invoicesrpc/invoices.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions lnrpc/invoicesrpc/invoices.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Collaborator

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 :)

*/
repeated uint64 private_channels = 10 [json_name = "private_channels"];
}

message AddHoldInvoiceResp {
Expand Down
1 change: 1 addition & 0 deletions lnrpc/invoicesrpc/invoices_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ func (s *Server) AddHoldInvoice(ctx context.Context,
FallbackAddr: invoice.FallbackAddr,
CltvExpiry: invoice.CltvExpiry,
Private: invoice.Private,
PrivateChannels: invoice.PrivateChannels,
}

_, dbInvoice, err := AddInvoice(ctx, addInvoiceCfg, addInvoiceData)
Expand Down
Loading