Skip to content

Commit

Permalink
Merge pull request #1224 from GeorgeTsagk/sendpayment-manual-rfq
Browse files Browse the repository at this point in the history
Support user-generated RFQ on `tchrpc.SendPayment`
  • Loading branch information
ffranr authored Dec 4, 2024
2 parents 35552e5 + 9da1d71 commit 77fa6dd
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 70 deletions.
81 changes: 81 additions & 0 deletions rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7034,6 +7034,87 @@ 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 must be 32 bytes in length")
}

// 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 _, q := range r.cfg.RfqManager.PeerAcceptedSellQuotes() {
if q.ID == rfqID {
qCopy := q
quote = &qCopy
break
}
}

// This quote ID did not match anything.
if quote == nil {
return fmt.Errorf("quote ID 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 fmt.Errorf("payment failed to send accepted "+
"sell order over stream: %v", err)
}

rpcsLog.Infof("Using quote for %v asset units at %v asset/BTC "+
"from peer %x with SCID %d", numAssetUnits,
rate.String(), 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
152 changes: 82 additions & 70 deletions taprpc/tapchannelrpc/tapchannel.pb.go

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

5 changes: 5 additions & 0 deletions taprpc/tapchannelrpc/tapchannel.proto
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ message SendPaymentRequest {
// contain a valid keysend record (key 5482373484 and a 32-byte preimage
// that corresponds to the payment hash).
routerrpc.SendPaymentRequest payment_request = 4;

// 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
5 changes: 5 additions & 0 deletions taprpc/tapchannelrpc/tapchannel.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,11 @@
"payment_request": {
"$ref": "#/definitions/routerrpcSendPaymentRequest",
"description": "The full lnd payment request to send. All fields behave the same way as\nthey do for lnd's routerrpc.SendPaymentV2 RPC method (see the API docs\nat https://lightning.engineering/api-docs/api/lnd/router/send-payment-v2\nfor more details).\nTo send a keysend payment, the payment_request.dest_custom_records must\ncontain a valid keysend record (key 5482373484 and a 32-byte preimage\nthat corresponds to the payment hash)."
},
"rfq_id": {
"type": "string",
"format": "byte",
"description": "The rfq id to use for this payment. If the user sets this value then the\npayment will immediately be dispatched, skipping the rfq negotiation\nphase, and using the following rfq id instead."
}
}
},
Expand Down

0 comments on commit 77fa6dd

Please sign in to comment.