Skip to content

Commit 1838d99

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 54287fc commit 1838d99

File tree

1 file changed

+68
-56
lines changed

1 file changed

+68
-56
lines changed

rpcserver.go

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6685,16 +6685,10 @@ func (r *rpcServer) checkPeerChannel(ctx context.Context, peer route.Vertex,
66856685
// For any other case, we'll want to make sure there is a channel with
66866686
// a non-zero balance of the given asset to carry the order.
66876687
default:
6688-
assetID, err := specifier.UnwrapIdOrErr()
6689-
if err != nil {
6690-
return fmt.Errorf("cannot check asset channel, " +
6691-
"missing asset ID")
6692-
}
6693-
66946688
// If we don't get an error here, it means we do have an asset
66956689
// channel with the peer. The intention doesn't matter as we're
66966690
// just checking whether a channel exists.
6697-
_, err = r.rfqChannel(ctx, assetID, &peer, NoIntention)
6691+
_, err := r.rfqChannel(ctx, specifier, &peer, NoIntention)
66986692
if err != nil {
66996693
return fmt.Errorf("error checking asset channel: %w",
67006694
err)
@@ -7370,9 +7364,11 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest,
73707364
peerPubKey = &parsedKey
73717365
}
73727366

7367+
specifier := asset.NewSpecifierFromId(assetID)
7368+
73737369
// We can now query the asset channels we have.
73747370
assetChan, err := r.rfqChannel(
7375-
ctx, assetID, peerPubKey, SendIntention,
7371+
ctx, specifier, peerPubKey, SendIntention,
73767372
)
73777373
if err != nil {
73787374
return fmt.Errorf("error finding asset channel to "+
@@ -7663,9 +7659,11 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
76637659
peerPubKey = &parsedKey
76647660
}
76657661

7662+
specifier := asset.NewSpecifierFromId(assetID)
7663+
76667664
// We can now query the asset channels we have.
76677665
assetChan, err := r.rfqChannel(
7668-
ctx, assetID, peerPubKey, ReceiveIntention,
7666+
ctx, specifier, peerPubKey, ReceiveIntention,
76697667
)
76707668
if err != nil {
76717669
return nil, fmt.Errorf("error finding asset channel to use: %w",
@@ -7952,60 +7950,59 @@ const (
79527950

79537951
// rfqChannel returns the channel to use for RFQ operations. If a peer public
79547952
// key is specified, the channels are filtered by that peer. If there are
7955-
// multiple channels for the same asset, the user must specify the peer public
7956-
// key.
7957-
func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
7953+
// multiple channels for the same specifier, the user must specify the peer
7954+
// public key.
7955+
func (r *rpcServer) rfqChannel(ctx context.Context, specifier asset.Specifier,
79587956
peerPubKey *route.Vertex,
7959-
intention chanIntention) (*channelWithAsset, error) {
7957+
intention chanIntention) (*channelWithSpecifier, error) {
79607958

7961-
balances, err := r.computeChannelAssetBalance(ctx)
7959+
balances, err := r.computeChannelAssetBalance(ctx, specifier)
79627960
if err != nil {
79637961
return nil, fmt.Errorf("error computing available asset "+
79647962
"channel balance: %w", err)
79657963
}
79667964

7967-
assetBalances, haveBalance := balances[id]
7968-
if !haveBalance || len(assetBalances) == 0 {
7969-
return nil, fmt.Errorf("no asset channel balance found for "+
7970-
"asset %s", id.String())
7965+
if len(balances) == 0 {
7966+
return nil, fmt.Errorf("no asset channel balance found for %s",
7967+
&specifier)
79717968
}
79727969

79737970
// If a peer public key was specified, we always want to use that to
79747971
// filter the asset channels.
79757972
if peerPubKey != nil {
7976-
assetBalances = fn.Filter(
7977-
assetBalances, func(c channelWithAsset) bool {
7973+
balances = fn.Filter(
7974+
balances, func(c channelWithSpecifier) bool {
79787975
return c.channelInfo.PubKeyBytes == *peerPubKey
79797976
},
79807977
)
79817978
}
79827979

79837980
switch {
7984-
// If there are multiple asset channels for the same asset, we need to
7985-
// ask the user to specify the peer public key. Otherwise, we don't know
7986-
// who to ask for a quote.
7987-
case len(assetBalances) > 1 && peerPubKey == nil:
7981+
// If there are multiple asset channels for the same specifier, we need
7982+
// to ask the user to specify the peer public key. Otherwise, we don't
7983+
// know who to ask for a quote.
7984+
case len(balances) > 1 && peerPubKey == nil:
79887985
return nil, fmt.Errorf("multiple asset channels found for "+
7989-
"asset %s, please specify the peer pubkey", id.String())
7986+
"%s, please specify the peer pubkey", &specifier)
79907987

79917988
// We don't have any channels with that asset ID and peer.
7992-
case len(assetBalances) == 0:
7993-
return nil, fmt.Errorf("no asset channel found for asset %s "+
7994-
"and peer %s", id.String(), peerPubKey.String())
7989+
case len(balances) == 0:
7990+
return nil, fmt.Errorf("no asset channel found for %s",
7991+
&specifier)
79957992
}
79967993

79977994
// If the user specified a peer public key, and we still have multiple
79987995
// channels, it means we have multiple channels with the same asset and
79997996
// the same peer, as we ruled out the rest of the cases above.
80007997

80017998
// Initialize best balance to first channel of the list.
8002-
bestBalance := assetBalances[0]
7999+
bestBalance := balances[0]
80038000

80048001
switch intention {
80058002
case ReceiveIntention:
80068003
// If the intention is to receive, return the channel
80078004
// with the best remote balance.
8008-
fn.ForEach(assetBalances, func(b channelWithAsset) {
8005+
fn.ForEach(balances, func(b channelWithSpecifier) {
80098006
if b.assetInfo.RemoteBalance >
80108007
bestBalance.assetInfo.RemoteBalance {
80118008

@@ -8016,7 +8013,7 @@ func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
80168013
case SendIntention:
80178014
// If the intention is to send, return the channel with
80188015
// the best local balance.
8019-
fn.ForEach(assetBalances, func(b channelWithAsset) {
8016+
fn.ForEach(balances, func(b channelWithSpecifier) {
80208017
if b.assetInfo.LocalBalance >
80218018
bestBalance.assetInfo.LocalBalance {
80228019

@@ -8032,28 +8029,33 @@ func (r *rpcServer) rfqChannel(ctx context.Context, id asset.ID,
80328029
return &bestBalance, nil
80338030
}
80348031

8035-
// channelWithAsset is a helper struct that combines the information of a single
8036-
// asset within a channel with the channels' general information.
8037-
type channelWithAsset struct {
8038-
// assetInfo is the information about one of the assets in a channel.
8039-
assetInfo rfqmsg.JsonAssetChanInfo
8032+
// channelWithSpecifier is a helper struct that combines the information of an
8033+
// asset specifier that is satisfied by a channel with the channels' general
8034+
// information.
8035+
type channelWithSpecifier struct {
8036+
// specifier is the asset specifier that is satisfied by this channels'
8037+
// assets.
8038+
specifier asset.Specifier
80408039

80418040
// channelInfo is the information about the channel the asset is
80428041
// committed to.
80438042
channelInfo lndclient.ChannelInfo
8043+
8044+
// assetInfo contains the asset related info of the channel.
8045+
assetInfo rfqmsg.JsonAssetChanInfo
80448046
}
80458047

80468048
// computeChannelAssetBalance computes the total local and remote balance for
8047-
// each asset channel.
8048-
func (r *rpcServer) computeChannelAssetBalance(
8049-
ctx context.Context) (map[asset.ID][]channelWithAsset, error) {
8049+
// each asset channel that matches the provided asset specifier.
8050+
func (r *rpcServer) computeChannelAssetBalance(ctx context.Context,
8051+
specifier asset.Specifier) ([]channelWithSpecifier, error) {
80508052

80518053
activeChannels, err := r.cfg.Lnd.Client.ListChannels(ctx, true, false)
80528054
if err != nil {
80538055
return nil, fmt.Errorf("unable to fetch channels: %w", err)
80548056
}
80558057

8056-
channelsByID := make(map[asset.ID][]channelWithAsset)
8058+
channels := make([]channelWithSpecifier, 0)
80578059
for chanIdx := range activeChannels {
80588060
openChan := activeChannels[chanIdx]
80598061
if len(openChan.CustomChannelData) == 0 {
@@ -8067,27 +8069,37 @@ func (r *rpcServer) computeChannelAssetBalance(
80678069
"data: %w", err)
80688070
}
80698071

8070-
for assetIdx := range assetData.Assets {
8071-
assetOutput := assetData.Assets[assetIdx]
8072-
assetIDStr := assetOutput.AssetInfo.AssetGenesis.AssetID
8073-
assetIDBytes, err := hex.DecodeString(assetIDStr)
8074-
if err != nil {
8075-
return nil, fmt.Errorf("error decoding asset "+
8076-
"ID: %w", err)
8072+
// Check if the assets of this channel match the provided
8073+
// specifier.
8074+
pass, err := r.cfg.RfqManager.ChannelCompatible(
8075+
ctx, assetData.Assets, specifier,
8076+
)
8077+
if err != nil {
8078+
return nil, err
8079+
}
8080+
8081+
if pass {
8082+
// Since the assets of the channel passed the above
8083+
// filter, we're safe to aggregate their info to be
8084+
// represented as a single entity.
8085+
var aggrInfo rfqmsg.JsonAssetChanInfo
8086+
8087+
// TODO(george): refactor when JSON gets fixed
8088+
for _, info := range assetData.Assets {
8089+
aggrInfo.Capacity += info.Capacity
8090+
aggrInfo.LocalBalance += info.LocalBalance
8091+
aggrInfo.RemoteBalance += info.RemoteBalance
80778092
}
8078-
var assetID asset.ID
8079-
copy(assetID[:], assetIDBytes)
80808093

8081-
channelsByID[assetID] = append(
8082-
channelsByID[assetID], channelWithAsset{
8083-
assetInfo: assetOutput,
8084-
channelInfo: openChan,
8085-
},
8086-
)
8094+
channels = append(channels, channelWithSpecifier{
8095+
specifier: specifier,
8096+
channelInfo: openChan,
8097+
assetInfo: aggrInfo,
8098+
})
80878099
}
80888100
}
80898101

8090-
return channelsByID, nil
8102+
return channels, nil
80918103
}
80928104

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

0 commit comments

Comments
 (0)