Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support user-generated RFQ on tchrpc.SendPayment #1224

Merged
merged 2 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
GeorgeTsagk marked this conversation as resolved.
Show resolved Hide resolved

// 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;
GeorgeTsagk marked this conversation as resolved.
Show resolved Hide resolved
}

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
Loading