Skip to content

Commit 28c4ea8

Browse files
author
ffranr
authored
Merge pull request #1357 from GeorgeTsagk/better-chan-selection
rpcserver: better rfq channel selection
2 parents 002f4ac + dbef1d4 commit 28c4ea8

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)