From 46c24bb882f2201168007591ecbc91a3fc6d98f0 Mon Sep 17 00:00:00 2001 From: George Tsagkarelis Date: Thu, 28 Nov 2024 17:04:56 +0100 Subject: [PATCH] rpcserver: skip rfq negotiation on manual SendPayment rfq --- rpcserver.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 993105115..d7215d82d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -7034,6 +7034,74 @@ func (r *rpcServer) SendPayment(req *tchrpc.SendPaymentRequest, case len(firstHopRecords) > 0: // Continue below. + case req.Scid != 0: + var quote rfqmsg.SellAccept + for id, q := range r.cfg.RfqManager.PeerAcceptedSellQuotes() { + if id == rfqmsg.SerialisedScid(req.Scid) { + quote = q + break + } + } + + if quote.ID == [32]byte{} { + return fmt.Errorf("scid did not match an accepted " + + "quote") + } + + 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(