Skip to content

Commit

Permalink
rpcserver: skip rfq negotiation on manual SendPayment rfq
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgeTsagk committed Dec 2, 2024
1 parent 4eb7e88 commit b7427dc
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 84 deletions.
86 changes: 86 additions & 0 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7034,6 +7034,92 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest,
case len(firstHopRecords) > 0:
// Continue below.

case req.RfqId != nil:
// Check if the provided rfq ID matches the expected length.
if len(req.RfqId) != 32 {
return fmt.Errorf("rfq id length must be 32")
}

// Now let's try to perform an internal lookup to see if there's
// an actual quote on this ID.
var rfqID rfqmsg.ID
copy(rfqID[:], req.RfqId)

var quote rfqmsg.SellAccept
for id, q := range r.cfg.RfqManager.PeerAcceptedSellQuotes() {
if id == rfqID.Scid() {
quote = q
break
}
}

// This quote ID's scid did not match anything.
if quote.ID == [32]byte{} {
return fmt.Errorf("scid did not match an accepted " +
"quote")
}

// This quote ID's scid matched a different quote.
if !bytes.Equal(quote.ID[:], req.RfqId) {
rpcsLog.Warnf("Quote %x produces scid=%v, scid match" +
"found, but quote ID is different.")
return fmt.Errorf("provided quote ID does not match")
}

invoice, err := zpay32.Decode(
pReq.PaymentRequest, r.cfg.Lnd.ChainParams,
)
if err != nil {
return fmt.Errorf("error decoding payment request: %w",
err)
}

rate := quote.AssetRate.Rate

// Calculate the equivalent asset units for the given invoice
// amount based on the asset-to-BTC conversion rate.
numAssetUnits := rfqmath.MilliSatoshiToUnits(
*invoice.MilliSat, rate,
)

sellOrder := &rfqrpc.PeerAcceptedSellQuote{
Peer: quote.Peer.String(),
Id: quote.ID[:],
Scid: uint64(quote.ID.Scid()),
BidAssetRate: &rfqrpc.FixedPoint{
Coefficient: rate.Coefficient.String(),
Scale: uint32(rate.Scale),
},
AssetAmount: numAssetUnits.ToUint64(),
Expiry: uint64(quote.AssetRate.Expiry.Unix()),
}

// Send out the information about the quote on the stream.
err = stream.Send(&tchrpc.SendPaymentResponse{
Result: &tchrpc.SendPaymentResponse_AcceptedSellOrder{
AcceptedSellOrder: sellOrder,
},
})
if err != nil {
return err
}

rpcsLog.Infof("Using quote for %v asset units at %v asset/BTC "+
"from peer %x with SCID %d", numAssetUnits, rate,
quote.Peer, quote.ID.Scid())

htlc := rfqmsg.NewHtlc(nil, fn.Some(quote.ID))

// We'll now map the HTLC struct into a set of TLV records,
// which we can then encode into the expected map format.
htlcMapRecords, err := tlv.RecordsToMap(htlc.Records())
if err != nil {
return fmt.Errorf("unable to encode records as map: %w",
err)
}

pReq.FirstHopCustomRecords = htlcMapRecords

// The request wants to pay a specific invoice.
case pReq.PaymentRequest != "":
invoice, err := zpay32.Decode(
Expand Down
154 changes: 77 additions & 77 deletions taprpc/tapchannelrpc/tapchannel.pb.go

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

8 changes: 4 additions & 4 deletions taprpc/tapchannelrpc/tapchannel.proto
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ message SendPaymentRequest {
// that corresponds to the payment hash).
routerrpc.SendPaymentRequest payment_request = 4;

// The rfq scid to use for this payment. If the user sets this value then
// the payment will immediately be dispatched, skipping the rfq negotiation
// phase, and using the following rfq scid.
uint64 scid = 5;
// The rfq id to use for this payment. If the user sets this value then the
// payment will immediately be dispatched, skipping the rfq negotiation
// phase, and using the following rfq id instead.
bytes rfq_id = 5;
}

message SendPaymentResponse {
Expand Down
Loading

0 comments on commit b7427dc

Please sign in to comment.