Skip to content

Commit 4b125be

Browse files
committed
rpcserver: use specifier to select rfq channels
When querying for channels we now provide the specifier, allowing the helper methods to check against the specifier with all the helpers that we introduced in the previous commits. Now a channel with an asset ID that belongs to a group, may qualify as valid "balance" of that group.
1 parent 38583eb commit 4b125be

File tree

1 file changed

+90
-61
lines changed

1 file changed

+90
-61
lines changed

rpcserver.go

+90-61
Original file line numberDiff line numberDiff line change
@@ -6569,16 +6569,10 @@ func (r *rpcServer) checkPeerChannel(ctx context.Context, peer route.Vertex,
65696569
// For any other case, we'll want to make sure there is a channel with
65706570
// a non-zero balance of the given asset to carry the order.
65716571
default:
6572-
assetID, err := specifier.UnwrapIdOrErr()
6573-
if err != nil {
6574-
return fmt.Errorf("cannot check asset channel, " +
6575-
"missing asset ID")
6576-
}
6577-
65786572
// If we don't get an error here, it means we do have an asset
65796573
// channel with the peer. The intention doesn't matter as we're
65806574
// just checking whether a channel exists.
6581-
_, err = r.rfqChannel(ctx, assetID, &peer, NoIntention)
6575+
_, err := r.rfqChannel(ctx, specifier, &peer, NoIntention)
65826576
if err != nil {
65836577
return fmt.Errorf("error checking asset channel: %w",
65846578
err)
@@ -7217,9 +7211,11 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest,
72177211
peerPubKey = &parsedKey
72187212
}
72197213

7214+
specifier := asset.NewSpecifierFromId(assetID)
7215+
72207216
// We can now query the asset channels we have.
72217217
assetChan, err := r.rfqChannel(
7222-
ctx, assetID, peerPubKey, SendIntention,
7218+
ctx, specifier, peerPubKey, SendIntention,
72237219
)
72247220
if err != nil {
72257221
return fmt.Errorf("error finding asset channel to "+
@@ -7510,9 +7506,11 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
75107506
peerPubKey = &parsedKey
75117507
}
75127508

7509+
specifier := asset.NewSpecifierFromId(assetID)
7510+
75137511
// We can now query the asset channels we have.
75147512
assetChan, err := r.rfqChannel(
7515-
ctx, assetID, peerPubKey, ReceiveIntention,
7513+
ctx, specifier, peerPubKey, ReceiveIntention,
75167514
)
75177515
if err != nil {
75187516
return nil, fmt.Errorf("error finding asset channel to use: %w",
@@ -7799,62 +7797,62 @@ const (
77997797

78007798
// rfqChannel returns the channel to use for RFQ operations. If a peer public
78017799
// key is specified, the channels are filtered by that peer. If there are
7802-
// multiple channels for the same asset, the user must specify the peer public
7803-
// key.
7804-
func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
7800+
// multiple channels for the same specifier, the user must specify the peer
7801+
// public key.
7802+
func (r *rpcServer) rfqChannel(ctx context.Context, specifier asset.Specifier,
78057803
peerPubKey *route.Vertex,
7806-
intention chanIntention) (*channelWithAsset, error) {
7804+
intention chanIntention) (*channelWithSpecifier, error) {
78077805

7808-
balances, err := r.computeChannelAssetBalance(ctx)
7806+
balances, err := r.computeChannelAssetBalance(ctx, specifier)
78097807
if err != nil {
78107808
return nil, fmt.Errorf("error computing available asset "+
78117809
"channel balance: %w", err)
78127810
}
78137811

7814-
assetBalances, haveBalance := balances[id]
7815-
if !haveBalance || len(assetBalances) == 0 {
7816-
return nil, fmt.Errorf("no asset channel balance found for "+
7817-
"asset %s", id.String())
7812+
if len(balances) == 0 {
7813+
return nil, fmt.Errorf("no asset channel balance found for %s",
7814+
specifier.String())
78187815
}
78197816

78207817
// If a peer public key was specified, we always want to use that to
78217818
// filter the asset channels.
78227819
if peerPubKey != nil {
7823-
assetBalances = fn.Filter(
7824-
assetBalances, func(c channelWithAsset) bool {
7820+
balances = fn.Filter(
7821+
balances, func(c channelWithSpecifier) bool {
78257822
return c.channelInfo.PubKeyBytes == *peerPubKey
78267823
},
78277824
)
78287825
}
78297826

78307827
switch {
7831-
// If there are multiple asset channels for the same asset, we need to
7832-
// ask the user to specify the peer public key. Otherwise, we don't know
7833-
// who to ask for a quote.
7834-
case len(assetBalances) > 1 && peerPubKey == nil:
7828+
// If there are multiple asset channels for the same specifier, we need
7829+
// to ask the user to specify the peer public key. Otherwise, we don't
7830+
// know who to ask for a quote.
7831+
case len(balances) > 1 && peerPubKey == nil:
78357832
return nil, fmt.Errorf("multiple asset channels found for "+
7836-
"asset %s, please specify the peer pubkey", id.String())
7833+
"%s, please specify the peer pubkey",
7834+
specifier.String())
78377835

78387836
// 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())
7837+
case len(balances) == 0:
7838+
return nil, fmt.Errorf("no asset channel found for %v",
7839+
specifier)
78427840
}
78437841

78447842
// If the user specified a peer public key, and we still have multiple
78457843
// channels, it means we have multiple channels with the same asset and
78467844
// the same peer, as we ruled out the rest of the cases above.
78477845

78487846
// Initialize best balance to first channel of the list.
7849-
bestBalance := assetBalances[0]
7847+
bestBalance := balances[0]
78507848

78517849
switch intention {
78527850
case ReceiveIntention:
78537851
// If the intention is to receive, return the channel
78547852
// with the best remote balance.
7855-
fn.ForEach(assetBalances, func(b channelWithAsset) {
7856-
if b.assetInfo.RemoteBalance >
7857-
bestBalance.assetInfo.RemoteBalance {
7853+
fn.ForEach(balances, func(b channelWithSpecifier) {
7854+
if b.channelInfo.RemoteBalance >
7855+
bestBalance.channelInfo.RemoteBalance {
78587856

78597857
bestBalance = b
78607858
}
@@ -7863,9 +7861,9 @@ func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
78637861
case SendIntention:
78647862
// If the intention is to send, return the channel with
78657863
// the best local balance.
7866-
fn.ForEach(assetBalances, func(b channelWithAsset) {
7867-
if b.assetInfo.LocalBalance >
7868-
bestBalance.assetInfo.LocalBalance {
7864+
fn.ForEach(balances, func(b channelWithSpecifier) {
7865+
if b.channelInfo.LocalBalance >
7866+
bestBalance.channelInfo.LocalBalance {
78697867

78707868
bestBalance = b
78717869
}
@@ -7879,28 +7877,64 @@ func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
78797877
return &bestBalance, nil
78807878
}
78817879

7882-
// channelWithAsset is a helper struct that combines the information of a single
7883-
// asset within a channel with the channels' general information.
7884-
type channelWithAsset struct {
7885-
// assetInfo is the information about one of the assets in a channel.
7886-
assetInfo rfqmsg.JsonAssetChanInfo
7880+
// channelWithSpecifier is a helper struct that combines the information of an
7881+
// asset specifier that is satisfied by a channel with the channels' general
7882+
// information.
7883+
type channelWithSpecifier struct {
7884+
// specifier is the asset specifier that is satisfied by this channels'
7885+
// assets.
7886+
specifier asset.Specifier
78877887

78887888
// channelInfo is the information about the channel the asset is
78897889
// committed to.
78907890
channelInfo lndclient.ChannelInfo
78917891
}
78927892

78937893
// computeChannelAssetBalance computes the total local and remote balance for
7894-
// each asset channel.
7895-
func (r *rpcServer) computeChannelAssetBalance(
7896-
ctx context.Context) (map[asset.ID][]channelWithAsset, error) {
7894+
// each asset channel that matches the provided asset specifier.
7895+
func (r *rpcServer) computeChannelAssetBalance(ctx context.Context,
7896+
specifier asset.Specifier) ([]channelWithSpecifier, error) {
78977897

78987898
activeChannels, err := r.cfg.Lnd.Client.ListChannels(ctx, true, false)
78997899
if err != nil {
79007900
return nil, fmt.Errorf("unable to fetch channels: %w", err)
79017901
}
79027902

7903-
channelsByID := make(map[asset.ID][]channelWithAsset)
7903+
// specifierFilter is a helper function that checks if the assets of a
7904+
// channel satisfy the provided asset specifier.
7905+
specifierFilter := func(
7906+
assets []rfqmsg.JsonAssetChanInfo) (bool, error) {
7907+
7908+
for assetIdx := range assets {
7909+
assetOutput := assets[assetIdx]
7910+
assetGen := assetOutput.AssetInfo.AssetGenesis
7911+
assetIDBytes, err := hex.DecodeString(
7912+
assetGen.AssetID,
7913+
)
7914+
if err != nil {
7915+
return false, fmt.Errorf("error "+
7916+
"decoding asset ID: %w", err)
7917+
}
7918+
7919+
var assetID asset.ID
7920+
copy(assetID[:], assetIDBytes)
7921+
7922+
match, err := r.cfg.RfqManager.AssetMatchesSpecifier(
7923+
ctx, specifier, assetID,
7924+
)
7925+
if err != nil {
7926+
return false, err
7927+
}
7928+
7929+
if !match {
7930+
return false, nil
7931+
}
7932+
}
7933+
7934+
return true, nil
7935+
}
7936+
7937+
channels := make([]channelWithSpecifier, 0)
79047938
for chanIdx := range activeChannels {
79057939
openChan := activeChannels[chanIdx]
79067940
if len(openChan.CustomChannelData) == 0 {
@@ -7914,27 +7948,22 @@ func (r *rpcServer) computeChannelAssetBalance(
79147948
"data: %w", err)
79157949
}
79167950

7917-
for assetIdx := range assetData.Assets {
7918-
assetOutput := assetData.Assets[assetIdx]
7919-
assetIDStr := assetOutput.AssetInfo.AssetGenesis.AssetID
7920-
assetIDBytes, err := hex.DecodeString(assetIDStr)
7921-
if err != nil {
7922-
return nil, fmt.Errorf("error decoding asset "+
7923-
"ID: %w", err)
7924-
}
7925-
var assetID asset.ID
7926-
copy(assetID[:], assetIDBytes)
7951+
// Check if the assets of this channel match the provided
7952+
// specifier.
7953+
pass, err := specifierFilter(assetData.Assets)
7954+
if err != nil {
7955+
return nil, err
7956+
}
79277957

7928-
channelsByID[assetID] = append(
7929-
channelsByID[assetID], channelWithAsset{
7930-
assetInfo: assetOutput,
7931-
channelInfo: openChan,
7932-
},
7933-
)
7958+
if pass {
7959+
channels = append(channels, channelWithSpecifier{
7960+
specifier: specifier,
7961+
channelInfo: openChan,
7962+
})
79347963
}
79357964
}
79367965

7937-
return channelsByID, nil
7966+
return channels, nil
79387967
}
79397968

79407969
// getInboundPolicy returns the policy of the given channel that points towards

0 commit comments

Comments
 (0)