Skip to content

Add Multi-RFQ Send #1613

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Add Multi-RFQ Send #1613

wants to merge 7 commits into from

Conversation

GeorgeTsagk
Copy link
Member

Description

Allows payments to use multiple quotes across multiple peers in order to pay an invoice. Previously we had to define a specific peer to negotiate a quote with, with this PR this is no longer required (but still supported) as Tapd will automatically scan our peers and establish quotes with all valid ones for the asset/amount of this payment.

The signature of ProduceHtlcExtraData had to be changed, as it's not possible to distinguish which of the quotes in the rfqmsg.Htlc should be used. We now provide the pubkey of the peer this HTLC is being sent to, in order to help Tapd extract the corresponding quote and calculate the correct amount of asset units.

Closes #1358

Depends on: lightningnetwork/lnd#9980

@GeorgeTsagk GeorgeTsagk self-assigned this Jun 23, 2025
@levmi levmi added enhancement New feature or request payment-channel RFQ Work relating to TAP channel Request For Quote (RFQ). tap-channels P1 labels Jun 23, 2025
@levmi levmi moved this from 🆕 New to 🏗 In progress in Taproot-Assets Project Board Jun 23, 2025
@levmi levmi requested review from guggero and ffranr June 23, 2025 15:36
Copy link
Member

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good! Have a couple of questions and suggestions, nothing major though.

if err != nil {
return err
}
list := make([]ID, num)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We allocate memory from a number we received over the wire. Need to check and error out the length before to make sure we limit the number of bytes we allocate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, so far the total length of available RFQ IDs is open ended.

We should introduce a static limit (which would also limit the max number of quotes we acquire) and enforce it everywhere.

@@ -456,16 +457,43 @@ func (s *AuxTrafficShaper) ProduceHtlcExtraData(totalAmount lnwire.MilliSatoshi,
return totalAmount, htlcCustomRecords, nil
}

if htlc.RfqID.ValOpt().IsNone() {
return 0, nil, fmt.Errorf("no RFQ ID present in HTLC blob")
if htlc.AvailableRfqIDs.IsNone() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here re backward compatibility. And also just to make sure we don't miss any edge case. After all, we explicitly set the singular htlc.RfqID in this function, so are we a 100% sure there is no code path where either the ProduceHtlcExtraData or PaymentBandwidth would be called with htlc.RfqID set?
IMO we should check both and only error out if none of them (or both) are set at the same time, with a comment that we'd only really expect the list to be set in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the PaymentBandwidth and ProduceHtlcExtraData the htlc.RfqID is replaced by htlc.AvailableRfqIDs

The only use of htlc.RfqID is when ProduceHtlcExtraData locks into a specific RFQ, which will be used to produce the actual HTLC that will be sent out to our peer

From that point forward everything is the same (we only use the htlc.RfqID to route HTLCs / accept HTLCs to invoices)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here re using an existing quote in the SendPayment RPC... Don't we have that covered by an itest?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap, we have it covered, and the itest was failing! so +1 for our coverage, but I realize I never noticed the itest failing

So the reason it failed is because we were setting the existing RPC user provided RFQ as the single RfqID, instead it had to change to instead set it as the only available RFQ ID in the new field

@coveralls
Copy link

coveralls commented Jun 26, 2025

Pull Request Test Coverage Report for Build 16071985844

Details

  • 70 of 313 (22.36%) changed or added relevant lines in 6 files are covered.
  • 10 unchanged lines in 4 files lost coverage.
  • Overall coverage increased (+17.1%) to 56.386%

Changes Missing Coverage Covered Lines Changed/Added Lines %
server.go 0 4 0.0%
fn/send.go 0 6 0.0%
rfqmsg/records.go 64 81 79.01%
tapchannel/aux_traffic_shaper.go 0 77 0.0%
rpcserver.go 3 142 2.11%
Files with Coverage Reduction New Missed Lines %
rpcserver.go 1 61.44%
asset/group_key.go 2 72.15%
commitment/tap.go 2 84.77%
tapchannel/aux_traffic_shaper.go 5 6.4%
Totals Coverage Status
Change from base Build 16059643780: 17.1%
Covered Lines: 57092
Relevant Lines: 101252

💛 - Coveralls

@GeorgeTsagk GeorgeTsagk requested a review from guggero June 26, 2025 14:30
@ZZiigguurraatt
Copy link

Please update

// The node identity public key of the peer to ask for a quote for sending
// out the assets and converting them to satoshis. This must be specified if
// there are multiple channels with the given asset ID.
bytes peer_pubkey = 3;
to reflect this new capability. Also, I think we need to be more specific to include group_key in addition to asset_id in there.

@ZZiigguurraatt
Copy link

What is this expected to do with an invoice with no amount specified?

@ZZiigguurraatt
Copy link

rfq_id is of type bytes

// 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;

but with multi-rfq send, I would expect the ability to provide an array. Not sure that you want to fix that in this PR, but maybe it should be a separate issue? I did not make this comment for multi-rfq receive because of #1442 .

Copy link
Member

@guggero guggero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did another pass, getting very close here too.

"outgoing channel")
// If the HTLC doesn't have any available RFQ IDs, it's incomplete, and
// we cannot determine the bandwidth.
if htlc.AvailableRfqIDs.IsNone() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you're 100% certain for all the code paths that lead into paymentBandwidth there isn't a single one where potentially we only have the old RFQ ID set? What about this for example:

nil, fn.Some(quote.ID), fn.None[[]rfqmsg.ID](),

default:
return 0, fmt.Errorf("no accepted quote found for RFQ ID "+
"%x (SCID %d)", rfqID[:], rfqID.Scid())
if bandwidth > 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Given we establish 1 quote per peer, only one of the RFQ IDs in the array should produce some bandwidth." would probably be a good comment to add above this statement.

@@ -456,16 +457,43 @@ func (s *AuxTrafficShaper) ProduceHtlcExtraData(totalAmount lnwire.MilliSatoshi,
return totalAmount, htlcCustomRecords, nil
}

if htlc.RfqID.ValOpt().IsNone() {
return 0, nil, fmt.Errorf("no RFQ ID present in HTLC blob")
if htlc.AvailableRfqIDs.IsNone() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here re using an existing quote in the SendPayment RPC... Don't we have that covered by an itest?

Copy link
Contributor

@ffranr ffranr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments around robustness within the context of multi peer RFQ queries.

rpcserver.go Outdated
Comment on lines 7731 to 7738
// For each peer that satisfies our query above, we'll try and
// establish an RFQ quote for the asset specifier and max amount
// of this payment.
for peer := range chanMap {
quote, err := r.acquireSellOrder(
ctx, &rpcSpecifier, paymentMaxAmt, expiry,
&peer,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the code would be better if this for-loop happened in a separate function.

I think acquireSellOrder is blocking, am I right? If so then the first peer could block until expiry (which i think is the invoice expiry) and then we don't have a chance to query any other peer.

We might need to call r.acquireSellOrder for each peer synchronously here. And the quote response timeout should be much less than the invoice expiry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the quote acquisition to be async, also used a shorter timeout for the RFQ negotiation

@ZZiigguurraatt
Copy link

Getting a vague error with litcli. Not sure why. Has anyone else tested mutli-RFQ send with litcli or only in itest?

24165ac30ed6:/$ litcli ln payinvoice --pay_req lnbcrt4440n1p5xdzkcpp5rk3tglvgl3nc8krwxv28qx4h6cvys33ta4ayhmzjcw97hs8hyj7qdqqcqzzsxqyz5vqsp5968vj7g9ngxv639jk4p9lu9mexcwlqp7r992xaj2645n0x8ay4ys9qxpqysgq46z9q5tgnq0t0e50vzsxwf7aq6cmwrajqyy0f79fe2s6jl3r40m3kxdcw8cd2q56eu6hvjdfkt8amyg0xznncejkn8mq4gp97xdsgngq6k3tgy --asset_id 12ef620e67294ac18f218e7bec769299d3eb33a3915aa3122fb1baafc14d0e53
Payment hash: 1da2b47d88fc6783d86e3314701ab7d61848462bed7a4bec52c38bebc0f724bc
Description: 
Amount (in satoshis): 444
Fee limit (in satoshis): 444
Destination: 02f57d125bb94141add3a82b9209858989000e70849005e9e031fdd6dbb388d6dd
Confirm payment (yes/no): yes
Got quote for 45065 asset units at 9 msat/unit from peer 02d63eec2b2dd001241e40a93d2b90c693f2efd8f011015accc0f73da0b22ad51e with SCID 17596861635263353475
[litcli] unexpected nil result
24165ac30ed6:/$ 

The RPC method now uses all of the introduced features. Instead of
acquiring just one quote we now extract that logic into a helper and
call it once for each valid peer. We then encode the array of available
RFQ IDs into the first hop records and hand it over to LND.
@GeorgeTsagk GeorgeTsagk requested a review from ffranr July 4, 2025 12:58
"outgoing channel")
// If the HTLC doesn't have any available RFQ IDs, it's incomplete, and
// we cannot determine the bandwidth.
if htlc.AvailableRfqIDs.IsNone() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a commit at the end of this PR that removes the single RFQ ID from the rfqmsg.NewHtlc() function. That way we're sure we don't accidentally have this problem in other places.

default:
return 0, fmt.Errorf("no accepted quote found for RFQ ID "+
"%x (SCID %d)", rfqID[:], rfqID.Scid())
if bandwidth > 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment still missing.

@@ -217,3 +217,7 @@ replace github.com/golang-migrate/migrate/v4 => github.com/lightninglabs/migrate

// Note this is a temproary replace and will be removed when taprpc is tagged.
replace github.com/lightninglabs/taproot-assets/taprpc => ./taprpc

replace github.com/lightningnetwork/lnd => github.com/GeorgeTsagk/lnd v0.0.0-20250702100924-4ad84627e108
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can bump this to v0.19.2-beta.rc1 (which should not need the sqldb rewrite anymore).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can bump this to v0.19.2-beta.rc1 (which should not need the sqldb rewrite anymore).

now it's v0.19.2-beta !

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like really this should remove the replace and update

github.com/lightningnetwork/lnd v0.19.1-beta.rc1.0.20250623232057-b48e2763a798
instead?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can bump this to v0.19.2-beta.rc1 (which should not need the sqldb rewrite anymore).

now it's v0.19.2-beta !

actually lnd v0.19.2-beta is not compatible with this PR because it does not use github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9

@@ -328,6 +340,10 @@ func (s *AuxTrafficShaper) paymentBandwidth(htlc *rfqmsg.Htlc,
return 0, err
}

// We know that we establish 1 quote per peer in the scope of
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, here it is. Please move this to the previous commit.


// multiRfqNegotiationTimeout is the timeout within which we expect our
// peer and our node to reach an agreement over a quote. This timeout
// is a bit shorter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: incomplete comment.

// We make sure to always write the result to a channel before
// returning. This way the collector can expect a certain number
// of items via the channels.
go func(peer route.Vertex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use errgroup.Group instead, would make the error cases a bit more explicit.

r.RejectedQuote.ErrorMessage)
// Send out the information about the acquired quotes on the
// stream.
for _, quote := range acquiredQuotes {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be extracted into a function, would make it a bit more explicit that this only informs the user and that call to rpcutils.UnmarshalRfqFixedPoin() is only for the log statement.

@ZZiigguurraatt
Copy link

Getting a vague error with litcli. Not sure why. Has anyone else tested mutli-RFQ send with litcli or only in itest?

24165ac30ed6:/$ litcli ln payinvoice --pay_req lnbcrt4440n1p5xdzkcpp5rk3tglvgl3nc8krwxv28qx4h6cvys33ta4ayhmzjcw97hs8hyj7qdqqcqzzsxqyz5vqsp5968vj7g9ngxv639jk4p9lu9mexcwlqp7r992xaj2645n0x8ay4ys9qxpqysgq46z9q5tgnq0t0e50vzsxwf7aq6cmwrajqyy0f79fe2s6jl3r40m3kxdcw8cd2q56eu6hvjdfkt8amyg0xznncejkn8mq4gp97xdsgngq6k3tgy --asset_id 12ef620e67294ac18f218e7bec769299d3eb33a3915aa3122fb1baafc14d0e53
Payment hash: 1da2b47d88fc6783d86e3314701ab7d61848462bed7a4bec52c38bebc0f724bc
Description: 
Amount (in satoshis): 444
Fee limit (in satoshis): 444
Destination: 02f57d125bb94141add3a82b9209858989000e70849005e9e031fdd6dbb388d6dd
Confirm payment (yes/no): yes
Got quote for 45065 asset units at 9 msat/unit from peer 02d63eec2b2dd001241e40a93d2b90c693f2efd8f011015accc0f73da0b22ad51e with SCID 17596861635263353475
[litcli] unexpected nil result
24165ac30ed6:/$ 

I seem to get this issue if the sender has multiple taproot asset channels. If the sender is a node with only a single taproot asset channel, it succeeds.

@ZZiigguurraatt
Copy link

ZZiigguurraatt commented Jul 9, 2025

I was having a problem where I could not make a direct asset payment from alice to bob over an asset channel to an asset invoice. I was getting

Invoice(hash=6a1272796e8d8fb7fdb9f29669c2e94a92bb1196847275c6deafb21484207bb1, amt=4466):  has asset custom records, but invoice does not require assets, canceling HTLCs

then I would also get FAILURE_REASON_INCORRECT_PAYMENT_DETAILS on the sender's side.

this went on for a while, but now I cannot reproduce anymore, the direct asset payment now succeeds.

Just want to make a comment here in case someone else sees this behavior, or as an initial data point if I get the problem to come back somehow.

@ZZiigguurraatt
Copy link

FYI: lightningnetwork/lnd#10056 is limiting my ability to do much complicated testing with this PR.

@ZZiigguurraatt
Copy link

I was having a problem where I could not make a direct asset payment from alice to bob over an asset channel to an asset invoice. I was getting

Invoice(hash=6a1272796e8d8fb7fdb9f29669c2e94a92bb1196847275c6deafb21484207bb1, amt=4466):  has asset custom records, but invoice does not require assets, canceling HTLCs

then I would also get FAILURE_REASON_INCORRECT_PAYMENT_DETAILS on the sender's side.

this went on for a while, but now I cannot reproduce anymore, the direct asset payment now succeeds.

Just want to make a comment here in case someone else sees this behavior, or as an initial data point if I get the problem to come back somehow.

OK, problem came back again. This time I was on another node and used

litcli ln payinvoice --group_key 036bd8b9572f3c8de9e8cd4f6df56752e7616c3930de84744182da9315c0cfff34 --rfq_peer_pubkey 03db56650f632360f465e39933f3771f5285c5e18f10cb93574406ed6e720aea4b lnbcrt4440n1p5xagj8pp5992egvzvhae5wfp9q7uu9xr2u766024eh9gr884hgu3z7cpp9cqqdqqcqzzsxqzfvrzjqfye02m7q27c6lxj27svf2zxl8cfnacjvs3vvnc0gddy0lwd8g9nmah0jnvw62y08sqqqqlgqqqqqqgq2qsp5pfm92s4avpk024vj5v9px9qfky60uzxpxfhexsm55smvf00jrnhs9qxpqysgq7cxnm3n4a60ecycc5cgw8cwhktuh604k3et3jtkras05k9jadk5jgk2slvmedq8eta94n6qeyemydlanp9fc234p4zq9s7l93um0szsqqywphd

to avoid #1613 (comment) , so it seems the problem is on the receiver's side and not sender's side.

On the receiver's side:

0c60be93a29f:/$ lncli getinfo|jq -r .identity_pubkey
03db56650f632360f465e39933f3771f5285c5e18f10cb93574406ed6e720aea4b
0c60be93a29f:/$ 

On the sender's side

c335aa6bc5a7:/$ lncli getinfo|jq -r .identity_pubkey
024997ab7e02bd8d7cd257a0c4a846f9f099f7126422c64f0f435a47fdcd3a0b3d
c335aa6bc5a7:/$ 

and also for reference

0c60be93a29f:/$ lncli decodepayreq lnbcrt4440n1p5xagj8pp5992egvzvhae5wfp9q7uu9xr2u766024eh9gr884hgu3z7cpp9cqqdqqcqzzsxqzfvrzjqfye02m7q27c6lxj27svf2zxl8cfnacjvs3vvnc0gddy0lwd8g9nmah0jnvw62y08sqqqqlgqqqqqqgq2qsp5pfm92s4avpk024vj5v9px9qfky60uzxpxfhexsm55smvf00jrnhs9qxpqysgq7cxnm3n4a60ecycc5cgw8cwhktuh604k3et3jtkras05k9jadk5jgk2slvmedq8eta94n6qeyemydlanp9fc234p4zq9s7l93um0szsqqywphd
{
    "destination": "03db56650f632360f465e39933f3771f5285c5e18f10cb93574406ed6e720aea4b",
    "payment_hash": "295594304cbf7347242507b9c2986ae7b5a7aab9b950339eb747222f60212e00",
    "num_satoshis": "444",
    "timestamp": "1752080967",
    "expiry": "300",
    "description": "",
    "description_hash": "",
    "fallback_addr": "",
    "cltv_expiry": "80",
    "route_hints": [
        {
            "hop_hints": [
                {
                    "node_id": "024997ab7e02bd8d7cd257a0c4a846f9f099f7126422c64f0f435a47fdcd3a0b3d",
                    "chan_id": "17793604312176824124",
                    "fee_base_msat": 1000,
                    "fee_proportional_millionths": 1,
                    "cltv_expiry_delta": 80
                }
            ]
        }
    ],
    "payment_addr": "0a765542bd606cf55592a30a131409b134fe08c1326f934374a436c4bdf21cef",
    "num_msat": "444000",
    "features": {
        "8": {
            "name": "tlv-onion",
            "is_required": true,
            "is_known": true
        },
        "14": {
            "name": "payment-addr",
            "is_required": true,
            "is_known": true
        },
        "17": {
            "name": "multi-path-payments",
            "is_required": false,
            "is_known": true
        },
        "25": {
            "name": "route-blinding",
            "is_required": false,
            "is_known": true
        }
    },
    "blinded_paths": []
}
0c60be93a29f:/$ 


@ZZiigguurraatt
Copy link

Getting a vague error with litcli. Not sure why. Has anyone else tested mutli-RFQ send with litcli or only in itest?

24165ac30ed6:/$ litcli ln payinvoice --pay_req lnbcrt4440n1p5xdzkcpp5rk3tglvgl3nc8krwxv28qx4h6cvys33ta4ayhmzjcw97hs8hyj7qdqqcqzzsxqyz5vqsp5968vj7g9ngxv639jk4p9lu9mexcwlqp7r992xaj2645n0x8ay4ys9qxpqysgq46z9q5tgnq0t0e50vzsxwf7aq6cmwrajqyy0f79fe2s6jl3r40m3kxdcw8cd2q56eu6hvjdfkt8amyg0xznncejkn8mq4gp97xdsgngq6k3tgy --asset_id 12ef620e67294ac18f218e7bec769299d3eb33a3915aa3122fb1baafc14d0e53
Payment hash: 1da2b47d88fc6783d86e3314701ab7d61848462bed7a4bec52c38bebc0f724bc
Description: 
Amount (in satoshis): 444
Fee limit (in satoshis): 444
Destination: 02f57d125bb94141add3a82b9209858989000e70849005e9e031fdd6dbb388d6dd
Confirm payment (yes/no): yes
Got quote for 45065 asset units at 9 msat/unit from peer 02d63eec2b2dd001241e40a93d2b90c693f2efd8f011015accc0f73da0b22ad51e with SCID 17596861635263353475
[litcli] unexpected nil result
24165ac30ed6:/$ 

I seem to get this issue if the sender has multiple taproot asset channels. If the sender is a node with only a single taproot asset channel, it succeeds.

As implied in #1613 (comment) , using --rfq_peer_pubkey also seems like it might be avoiding this issue on a node with multiple channels.

@ZZiigguurraatt
Copy link

Getting a vague error with litcli. Not sure why. Has anyone else tested mutli-RFQ send with litcli or only in itest?

24165ac30ed6:/$ litcli ln payinvoice --pay_req lnbcrt4440n1p5xdzkcpp5rk3tglvgl3nc8krwxv28qx4h6cvys33ta4ayhmzjcw97hs8hyj7qdqqcqzzsxqyz5vqsp5968vj7g9ngxv639jk4p9lu9mexcwlqp7r992xaj2645n0x8ay4ys9qxpqysgq46z9q5tgnq0t0e50vzsxwf7aq6cmwrajqyy0f79fe2s6jl3r40m3kxdcw8cd2q56eu6hvjdfkt8amyg0xznncejkn8mq4gp97xdsgngq6k3tgy --asset_id 12ef620e67294ac18f218e7bec769299d3eb33a3915aa3122fb1baafc14d0e53
Payment hash: 1da2b47d88fc6783d86e3314701ab7d61848462bed7a4bec52c38bebc0f724bc
Description: 
Amount (in satoshis): 444
Fee limit (in satoshis): 444
Destination: 02f57d125bb94141add3a82b9209858989000e70849005e9e031fdd6dbb388d6dd
Confirm payment (yes/no): yes
Got quote for 45065 asset units at 9 msat/unit from peer 02d63eec2b2dd001241e40a93d2b90c693f2efd8f011015accc0f73da0b22ad51e with SCID 17596861635263353475
[litcli] unexpected nil result
24165ac30ed6:/$ 

I seem to get this issue if the sender has multiple taproot asset channels. If the sender is a node with only a single taproot asset channel, it succeeds.

As implied in #1613 (comment) , using --rfq_peer_pubkey also seems like it might be avoiding this issue on a node with multiple channels.

#1565 (comment) might explain why litcli ln payinvoice is giving this weird error?

@ZZiigguurraatt
Copy link

ZZiigguurraatt commented Jul 9, 2025

Before we merge this PR, I think you all should look at #1565 (comment) and make sure that this is the way we want to do it so that we know that the fix for #1565 for AddInvoice is going to be consistent.

@ZZiigguurraatt
Copy link

Before we merge this PR, I think you all should look at #1565 (comment) and make sure that this is the way we want to do it so that we know that the fix for #1565 for AddInvoice is going to be consistent.

From conversations offline, it sounds like we probably do want to change how this works and add a new field which is an array and eventually deprecate the old accepted_sell_order field. Reasons for this are:

  • the way SendPayment keeps streaming a new value of the accepted_sell_order field, the client doesn't know when it is done.
  • we don't have any plans to make an async return of accepted_sell_order, currently we wait for all quotes to be received and that is what we should continue to do.

@lightninglabs-deploy
Copy link

@ffranr: review reminder
@GeorgeTsagk, remember to re-request review from reviewers when ready

@@ -217,3 +217,7 @@ replace github.com/golang-migrate/migrate/v4 => github.com/lightninglabs/migrate

// Note this is a temproary replace and will be removed when taprpc is tagged.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this still needed?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like can we change

github.com/lightninglabs/taproot-assets/taprpc v1.0.8
to v1.0.9 ?


replace github.com/lightningnetwork/lnd => github.com/GeorgeTsagk/lnd v0.0.0-20250702100924-4ad84627e108

replace github.com/lightningnetwork/lnd/sqldb => github.com/GeorgeTsagk/lnd/sqldb v0.0.0-20250702100924-4ad84627e108

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with this one

github.com/lightningnetwork/lnd/sqldb v1.0.10 // indirect

@@ -128,7 +128,7 @@ require (
github.com/lightninglabs/lightning-node-connect/gbn v1.0.1 // indirect
github.com/lightninglabs/lightning-node-connect/mailbox v1.0.1 // indirect
github.com/lightninglabs/neutrino v0.16.1 // indirect
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb // indirect
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9 // indirect

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of this change? If I rebase this PR onto main and keep this line, I get

# github.com/lightningnetwork/lnd/routing/blindedpath
/home/zzz/go/pkg/mod/github.com/lightningnetwork/[email protected]/routing/blindedpath/blinded_path.go:291:21: blindedPath.BlindedHops undefined (type *sphinx.BlindedPathInfo has no field or method BlindedHops)
/home/zzz/go/pkg/mod/github.com/lightningnetwork/[email protected]/routing/blindedpath/blinded_path.go:300:14: blindedPath.BlindedHops undefined (type *sphinx.BlindedPathInfo has no field or method BlindedHops)
/home/zzz/go/pkg/mod/github.com/lightningnetwork/[email protected]/routing/blindedpath/blinded_path.go:301:15: blindedPath.IntroductionPoint undefined (type *sphinx.BlindedPathInfo has no field or method IntroductionPoint)
/home/zzz/go/pkg/mod/github.com/lightningnetwork/[email protected]/routing/blindedpath/blinded_path.go:311:44: blindedPath.BlindingPoint undefined (type *sphinx.BlindedPathInfo has no field or method BlindingPoint)
/home/zzz/go/pkg/mod/github.com/lightningnetwork/[email protected]/routing/blindedpath/blinded_path.go:312:44: blindedPath.BlindedHops undefined (type *sphinx.BlindedPathInfo has no field or method BlindedHops)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems tapd main branch is on lnd v0.19.2-beta, but lnd v0.19.2-beta does not yet use github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9, so that is the cause of the error messages. it seems lightningnetwork/lnd#9980 was cherry picked onto lnd v0.19.2-beta off of master and that is why I got confused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request P1 payment-channel RFQ Work relating to TAP channel Request For Quote (RFQ). tap-channels
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

[feature]: Multi-RFQ send
7 participants