Skip to content

Commit dbef1d4

Browse files
committed
rpcserver: better rfq channel selection
Previously, callers of rfqChannel would just get the first channel from the list of candidates. This is sufficient, but we could easily optimise this depending on the intention. Depending on whether we want to receive or send over the channel, we return the channel with the best remote or local balance accordingly.
1 parent 002f4ac commit dbef1d4

File tree

1 file changed

+66
-13
lines changed

1 file changed

+66
-13
lines changed

rpcserver.go

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6576,8 +6576,9 @@ func (r *rpcServer) checkPeerChannel(ctx context.Context, peer route.Vertex,
65766576
}
65776577

65786578
// If we don't get an error here, it means we do have an asset
6579-
// channel with the peer.
6580-
_, err = r.rfqChannel(ctx, assetID, &peer)
6579+
// channel with the peer. The intention doesn't matter as we're
6580+
// just checking whether a channel exists.
6581+
_, err = r.rfqChannel(ctx, assetID, &peer, NoIntention)
65816582
if err != nil {
65826583
return fmt.Errorf("error checking asset channel: %w",
65836584
err)
@@ -7217,7 +7218,9 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest,
72177218
}
72187219

72197220
// We can now query the asset channels we have.
7220-
assetChan, err := r.rfqChannel(ctx, assetID, peerPubKey)
7221+
assetChan, err := r.rfqChannel(
7222+
ctx, assetID, peerPubKey, SendIntention,
7223+
)
72217224
if err != nil {
72227225
return fmt.Errorf("error finding asset channel to "+
72237226
"use: %w", err)
@@ -7508,7 +7511,9 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
75087511
}
75097512

75107513
// We can now query the asset channels we have.
7511-
assetChan, err := r.rfqChannel(ctx, assetID, peerPubKey)
7514+
assetChan, err := r.rfqChannel(
7515+
ctx, assetID, peerPubKey, ReceiveIntention,
7516+
)
75127517
if err != nil {
75137518
return nil, fmt.Errorf("error finding asset channel to use: %w",
75147519
err)
@@ -7775,12 +7780,30 @@ func (r *rpcServer) DecDisplayForAssetID(ctx context.Context,
77757780
return meta.DecDisplayOption()
77767781
}
77777782

7783+
// chanIntention defines the intention of calling rfqChannel. This helps with
7784+
// returning the channel that is most suitable for what we want to do.
7785+
type chanIntention uint8
7786+
7787+
const (
7788+
// NoIntention defines the absence of any intention, signalling that we
7789+
// don't really care which channel is returned.
7790+
NoIntention chanIntention = iota
7791+
7792+
// SendIntention defines the intention to send over an asset channel.
7793+
SendIntention
7794+
7795+
// ReceiveIntention defines the intention to receive over an asset
7796+
// channel.
7797+
ReceiveIntention
7798+
)
7799+
77787800
// rfqChannel returns the channel to use for RFQ operations. If a peer public
77797801
// key is specified, the channels are filtered by that peer. If there are
77807802
// multiple channels for the same asset, the user must specify the peer public
77817803
// key.
77827804
func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
7783-
peerPubKey *route.Vertex) (*channelWithAsset, error) {
7805+
peerPubKey *route.Vertex,
7806+
intention chanIntention) (*channelWithAsset, error) {
77847807

77857808
balances, err := r.computeChannelAssetBalance(ctx)
77867809
if err != nil {
@@ -7812,18 +7835,48 @@ func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
78127835
return nil, fmt.Errorf("multiple asset channels found for "+
78137836
"asset %s, please specify the peer pubkey", id.String())
78147837

7838+
// We don't have any channels with that asset ID and peer.
7839+
case len(assetBalances) == 0:
7840+
return nil, fmt.Errorf("no asset channel found for asset %s "+
7841+
"and peer %s", id.String(), peerPubKey.String())
7842+
}
7843+
78157844
// If the user specified a peer public key, and we still have multiple
78167845
// channels, it means we have multiple channels with the same asset and
7817-
// the same peer. So we just return the first channel.
7818-
case len(assetBalances) >= 1:
7819-
return &assetBalances[0], nil
7846+
// the same peer, as we ruled out the rest of the cases above.
78207847

7821-
// The default case is: We don't have any channels with that asset ID
7822-
// and peer.
7823-
default:
7824-
return nil, fmt.Errorf("no asset channel found for asset %s "+
7825-
"and peer %s", id.String(), peerPubKey.String())
7848+
// Initialize best balance to first channel of the list.
7849+
bestBalance := assetBalances[0]
7850+
7851+
switch intention {
7852+
case ReceiveIntention:
7853+
// If the intention is to receive, return the channel
7854+
// with the best remote balance.
7855+
fn.ForEach(assetBalances, func(b channelWithAsset) {
7856+
if b.assetInfo.RemoteBalance >
7857+
bestBalance.assetInfo.RemoteBalance {
7858+
7859+
bestBalance = b
7860+
}
7861+
})
7862+
7863+
case SendIntention:
7864+
// If the intention is to send, return the channel with
7865+
// the best local balance.
7866+
fn.ForEach(assetBalances, func(b channelWithAsset) {
7867+
if b.assetInfo.LocalBalance >
7868+
bestBalance.assetInfo.LocalBalance {
7869+
7870+
bestBalance = b
7871+
}
7872+
})
7873+
7874+
case NoIntention:
7875+
// Do nothing. Just return the first element that was
7876+
// assigned above.
78267877
}
7878+
7879+
return &bestBalance, nil
78277880
}
78287881

78297882
// channelWithAsset is a helper struct that combines the information of a single

0 commit comments

Comments
 (0)