diff --git a/Makefile b/Makefile index 31ee0b937..1df75054c 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ GO_VERSION = 1.23.9 # installed before running the integration tests which include backward # compatibility tests. The list of versions must be in sync with any version # used in the backwardCompat map in itest/litd_test_list_on_test.go. -LITD_COMPAT_VERSIONS = v0.14.1-alpha +LITD_COMPAT_VERSIONS = v0.14.1-alpha v0.15.0-alpha LOOP_COMMIT := $(shell cat go.mod | \ grep $(LOOP_PKG) | \ diff --git a/go.mod b/go.mod index f66f992f5..c4a7610d2 100644 --- a/go.mod +++ b/go.mod @@ -25,23 +25,23 @@ require ( github.com/lightninglabs/lightning-terminal/autopilotserverrpc v0.0.3 github.com/lightninglabs/lightning-terminal/litrpc v1.0.2 github.com/lightninglabs/lightning-terminal/perms v1.0.1 - github.com/lightninglabs/lndclient v0.19.0-7 - github.com/lightninglabs/loop v0.31.2-beta + github.com/lightninglabs/lndclient v0.19.0-9 + github.com/lightninglabs/loop v0.31.2-beta.0.20250623124517-3714ad8c90be github.com/lightninglabs/loop/looprpc v1.0.8 github.com/lightninglabs/loop/swapserverrpc v1.0.15 github.com/lightninglabs/pool v0.6.6-beta github.com/lightninglabs/pool/auctioneerrpc v1.1.3 github.com/lightninglabs/pool/poolrpc v1.0.1 - github.com/lightninglabs/taproot-assets v0.6.0 - github.com/lightninglabs/taproot-assets/taprpc v1.0.7 - github.com/lightningnetwork/lnd v0.19.1-beta + github.com/lightninglabs/taproot-assets v0.6.1-0.20250702102724-019b54a08035 + github.com/lightninglabs/taproot-assets/taprpc v1.0.9-0.20250626110400-df8ce528d7ff + github.com/lightningnetwork/lnd v0.19.1-beta.rc1.0.20250623232057-b48e2763a798 github.com/lightningnetwork/lnd/cert v1.2.2 github.com/lightningnetwork/lnd/clock v1.1.1 github.com/lightningnetwork/lnd/fn v1.2.3 github.com/lightningnetwork/lnd/fn/v2 v2.0.8 github.com/lightningnetwork/lnd/kvdb v1.4.16 - github.com/lightningnetwork/lnd/sqldb v1.0.9 - github.com/lightningnetwork/lnd/tlv v1.3.1 + github.com/lightningnetwork/lnd/sqldb v1.0.10 + github.com/lightningnetwork/lnd/tlv v1.3.2 github.com/lightningnetwork/lnd/tor v1.1.6 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 @@ -148,7 +148,7 @@ require ( github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.3 // indirect github.com/lightninglabs/neutrino v0.16.1 // indirect github.com/lightninglabs/neutrino/cache v1.1.2 // 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 github.com/lightningnetwork/lnd/healthcheck v1.2.6 // indirect github.com/lightningnetwork/lnd/queue v1.1.1 // indirect github.com/lightningnetwork/lnd/ticker v1.1.1 // indirect @@ -247,3 +247,7 @@ replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-d // it is a replace in the tapd repository, it doesn't get propagated here // automatically, so we need to add it manually. replace github.com/golang-migrate/migrate/v4 => github.com/lightninglabs/migrate/v4 v4.18.2-9023d66a-fork-pr-2 + +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 diff --git a/go.sum b/go.sum index c24230d13..21158bdb0 100644 --- a/go.sum +++ b/go.sum @@ -603,6 +603,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/GeorgeTsagk/lnd v0.0.0-20250702100924-4ad84627e108 h1:iYNorZQIyJg4Fd2QGKCcUd30zJTXJTsorRFir9e6488= +github.com/GeorgeTsagk/lnd v0.0.0-20250702100924-4ad84627e108/go.mod h1:s8TSzKAEoXyzjOGsm9AXm/kIT1Hiugg7J15bykFM2y4= +github.com/GeorgeTsagk/lnd/sqldb v0.0.0-20250702100924-4ad84627e108 h1:2oAtHljJVzVDG+wVrnd/XCE59dDXDnfxxEqVWE1eeas= +github.com/GeorgeTsagk/lnd/sqldb v0.0.0-20250702100924-4ad84627e108/go.mod h1:c/vWoQfcxu6FAfHzGajkIQi7CEIeIZFhhH4DYh1BJpc= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= @@ -1150,10 +1154,10 @@ github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.3 h1:NuDp6Z+QNM github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.3/go.mod h1:bDnEKRN1u13NFBuy/C+bFLhxA5bfd3clT25y76QY0AM= github.com/lightninglabs/lightning-node-connect/mailbox v1.0.1 h1:RWmohykp3n/DTMWY8b18RNTEcLDf+KT/AZHKYdOObkM= github.com/lightninglabs/lightning-node-connect/mailbox v1.0.1/go.mod h1:NYtNexZE9gO1eOeegTxmIW9fqanl7eZ9cOrE9yewSAk= -github.com/lightninglabs/lndclient v0.19.0-7 h1:8+wGQnO8KSUq9elzGLscBUGchID+bWvrpX2qCo+tU48= -github.com/lightninglabs/lndclient v0.19.0-7/go.mod h1:35d50tEMFxlJlKTZGYA6EdOllPsbxS4FUmEVbETUx+Q= -github.com/lightninglabs/loop v0.31.2-beta h1:lm5t5FqDpSfQCxoz/vTvXpylxSgU+gvJJIbfJiKeyUk= -github.com/lightninglabs/loop v0.31.2-beta/go.mod h1:xnPKuZmLusNERwzz15RZ7mpQ8xuSqqh3g8Qw/PRyiRE= +github.com/lightninglabs/lndclient v0.19.0-9 h1:ell27omDoks79upoAsO/7QY40O93ud4tAtBXXZilqok= +github.com/lightninglabs/lndclient v0.19.0-9/go.mod h1:35d50tEMFxlJlKTZGYA6EdOllPsbxS4FUmEVbETUx+Q= +github.com/lightninglabs/loop v0.31.2-beta.0.20250623124517-3714ad8c90be h1:Xoq4cSKbxuuwLewh7+C7VdBiSUwVND6h9waSuOeWqSk= +github.com/lightninglabs/loop v0.31.2-beta.0.20250623124517-3714ad8c90be/go.mod h1:BleoAw0V7NFw0K1COMiIZE2nS606HfW4RO3yYl0C7hg= github.com/lightninglabs/loop/looprpc v1.0.8 h1:OFmJNLjem6fLuH1YUO+3G6QA1wmjAd0zyhvdHONOBDs= github.com/lightninglabs/loop/looprpc v1.0.8/go.mod h1:c7WykKQZ3PspCMVvv2kr9o4l3bgJBEBVv0SOoBOjPOw= github.com/lightninglabs/loop/swapserverrpc v1.0.15 h1:vEZBF65Lv0T7MPydCRxHSIlEJzHBkZ4I8FtSD6OJK88= @@ -1172,14 +1176,12 @@ github.com/lightninglabs/pool/poolrpc v1.0.1 h1:XbNx28TYwEj/PVsnnF9TnveVCMCYfS1v github.com/lightninglabs/pool/poolrpc v1.0.1/go.mod h1:836icifg/SBnZbiae0v3jeRRzCrT6LWo32SqCS/JiGk= github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display h1:w7FM5LH9Z6CpKxl13mS48idsu6F+cEZf0lkyiV+Dq9g= github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -github.com/lightninglabs/taproot-assets v0.6.0 h1:nHloX+QR2PbUmogry1T+LiYh1TWBoFnTMHOy4Hyq1VM= -github.com/lightninglabs/taproot-assets v0.6.0/go.mod h1:CkK0drLPo5M6ib9YRE3lD+znOfe0Oxh6zMvGN1SJXDo= -github.com/lightninglabs/taproot-assets/taprpc v1.0.7 h1:yUG9vdpajiU0gp4wDkTPz/6BI8Vr52OM2paahlVrAys= -github.com/lightninglabs/taproot-assets/taprpc v1.0.7/go.mod h1:vOM2Ap2wYhEZjiJU7bNNg+e5tDxkvRAuyXwf/KQ4tgo= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= -github.com/lightningnetwork/lnd v0.19.1-beta h1:lIixXD/CemfvFFU2pWzGciOGRZ8vuQNPCzpKn/xt8zA= -github.com/lightningnetwork/lnd v0.19.1-beta/go.mod h1:iHZ/FHFK00BqV6qgDkZZfqWE3LGtgE0U5KdO5WrM+eQ= +github.com/lightninglabs/taproot-assets v0.6.1-0.20250702102724-019b54a08035 h1:XwnFiYBbFXfp4EDI7MQUeYk1QZk/KmXmf94qED2hw9k= +github.com/lightninglabs/taproot-assets v0.6.1-0.20250702102724-019b54a08035/go.mod h1:sAHZLKGmLboBH1QUDwWUY6xrLHHrmb1prPxiZqqvT14= +github.com/lightninglabs/taproot-assets/taprpc v1.0.9-0.20250626110400-df8ce528d7ff h1:1axz5jqDUYxl8mk4P8lU6PYTWbRLiZgrhKi75dqrBhE= +github.com/lightninglabs/taproot-assets/taprpc v1.0.9-0.20250626110400-df8ce528d7ff/go.mod h1:vOM2Ap2wYhEZjiJU7bNNg+e5tDxkvRAuyXwf/KQ4tgo= +github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9 h1:6D3LrdagJweLLdFm1JNodZsBk6iU4TTsBBFLQ4yiXfI= +github.com/lightningnetwork/lightning-onion v1.2.1-0.20240815225420-8b40adf04ab9/go.mod h1:EDqJ3MuZIbMq0QI1czTIKDJ/GS8S14RXPwapHw8cw6w= github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI= github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U= github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= @@ -1194,12 +1196,10 @@ github.com/lightningnetwork/lnd/kvdb v1.4.16 h1:9BZgWdDfjmHRHLS97cz39bVuBAqMc4/p github.com/lightningnetwork/lnd/kvdb v1.4.16/go.mod h1:HW+bvwkxNaopkz3oIgBV6NEnV4jCEZCACFUcNg4xSjM= github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= -github.com/lightningnetwork/lnd/sqldb v1.0.9 h1:7OHi+Hui823mB/U9NzCdlZTAGSVdDCbjp33+6d/Q+G0= -github.com/lightningnetwork/lnd/sqldb v1.0.9/go.mod h1:OG09zL/PHPaBJefp4HsPz2YLUJ+zIQHbpgCtLnOx8I4= github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= -github.com/lightningnetwork/lnd/tlv v1.3.1 h1:o7CZg06y+rJZfUMAo0WzBLr0pgBWCzrt0f9gpujYUzk= -github.com/lightningnetwork/lnd/tlv v1.3.1/go.mod h1:pJuiBj1ecr1WWLOtcZ+2+hu9Ey25aJWFIsjmAoPPnmc= +github.com/lightningnetwork/lnd/tlv v1.3.2 h1:MO4FCk7F4k5xPMqVZF6Nb/kOpxlwPrUQpYjmyKny5s0= +github.com/lightningnetwork/lnd/tlv v1.3.2/go.mod h1:pJuiBj1ecr1WWLOtcZ+2+hu9Ey25aJWFIsjmAoPPnmc= github.com/lightningnetwork/lnd/tor v1.1.6 h1:WHUumk7WgU6BUFsqHuqszI9P6nfhMeIG+rjJBlVE6OE= github.com/lightningnetwork/lnd/tor v1.1.6/go.mod h1:qSRB8llhAK+a6kaTPWOLLXSZc6Hg8ZC0mq1sUQ/8JfI= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= diff --git a/itest/assets_test.go b/itest/assets_test.go index 1fb456dac..da852e3bf 100644 --- a/itest/assets_test.go +++ b/itest/assets_test.go @@ -27,6 +27,7 @@ import ( "github.com/lightninglabs/taproot-assets/tapfreighter" "github.com/lightninglabs/taproot-assets/taprpc" "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc" + "github.com/lightninglabs/taproot-assets/taprpc/authmailboxrpc" "github.com/lightninglabs/taproot-assets/taprpc/mintrpc" "github.com/lightninglabs/taproot-assets/taprpc/rfqrpc" tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc" @@ -76,25 +77,32 @@ type itestNode struct { // multiRfqNodes contains all the itest nodes that are required to set up the // multi RFQ network topology. type multiRfqNodes struct { - charlie, dave, erin, fabia, yara itestNode - universeTap *tapClient + charlie, dave, erin, fabia, yara, george itestNode + universeTap *tapClient } // createTestMultiRFQAssetNetwork creates a lightning network topology which // consists of both bitcoin and asset channels. It focuses on the property of // having multiple channels available on both the sender and receiver side. +// The George node is using a way different oracle that provides asset rates +// that fall outside of the configured tolerance bounds, leading to RFQ +// negotiation failures. // // The topology we are going for looks like the following: // -// /---[sats]--> Erin --[assets]--\ -// / \ -// / \ +// /---[sats]--> Erin --[assets]--\ +// / \ +// / \ +// / \ // -// Charlie -----[sats]--> Dave --[assets]---->Fabia +// Charlie -----[sats]--> Dave --[assets]--> Fabia // -// \ / -// \ / -// \---[sats]--> Yara --[assets]--/ +// \ / / +// \ / / +// \---[sats]--> Yara --[assets]-----/ / +// \ / +// \ / +// \--[sats]-> George --[assets]-/ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, nodes multiRfqNodes, mintedAsset *taprpc.Asset, assetSendAmount, fundingAmount uint64, pushSat int64) (*lnrpc.ChannelPoint, @@ -105,6 +113,7 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, erin, erinTap := nodes.erin.Lnd, nodes.erin.Tapd _, fabiaTap := nodes.fabia.Lnd, nodes.fabia.Tapd yara, yaraTap := nodes.yara.Lnd, nodes.yara.Tapd + george, georgeTap := nodes.george.Lnd, nodes.george.Tapd universeTap := nodes.universeTap // Let's open the normal sats channels between Charlie and the routing @@ -130,6 +139,13 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, }, ) + _ = openChannelAndAssert( + t, net, charlie, george, lntest.OpenChannelParams{ + Amt: 10_000_000, + SatPerVByte: 5, + }, + ) + ctxb := context.Background() assetID := mintedAsset.AssetGenesis.AssetId var groupKey []byte @@ -224,6 +240,34 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, ) itest.AssertNonInteractiveRecvComplete(t.t, yaraTap, 1) + // We need to send some assets to George, so he can fund an asset + // channel with Fabia. + georgeAddr, err := georgeTap.NewAddr(ctxb, &taprpc.NewAddrRequest{ + Amt: assetSendAmount, + AssetId: assetID, + ProofCourierAddr: fmt.Sprintf( + "%s://%s", proof.UniverseRpcCourierType, + charlieTap.node.Cfg.LitAddr(), + ), + }) + require.NoError(t.t, err) + + t.Logf("Sending %v asset units to George...", assetSendAmount) + + // Send the assets to George. + itest.AssertAddrCreated(t.t, georgeTap, mintedAsset, georgeAddr) + sendResp, err = charlieTap.SendAsset(ctxb, &taprpc.SendAssetRequest{ + TapAddrs: []string{georgeAddr.Encoded}, + }) + require.NoError(t.t, err) + itest.ConfirmAndAssertOutboundTransfer( + t.t, t.lndHarness.Miner.Client, charlieTap, sendResp, assetID, + []uint64{ + mintedAsset.Amount - 4*assetSendAmount, assetSendAmount, + }, 3, 4, + ) + itest.AssertNonInteractiveRecvComplete(t.t, georgeTap, 1) + // We fund the Dave->Fabia channel. fundRespDF, err := daveTap.FundChannel( ctxb, &tchrpc.FundChannelRequest{ @@ -263,6 +307,19 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, require.NoError(t.t, err) t.Logf("Funded channel between Yara and Fabia: %v", fundRespYF) + // We fund the Yara->Fabia channel. + fundRespGF, err := georgeTap.FundChannel( + ctxb, &tchrpc.FundChannelRequest{ + AssetAmount: fundingAmount, + AssetId: assetID, + PeerPubkey: fabiaTap.node.PubKey[:], + FeeRateSatPerVbyte: 5, + PushSat: pushSat, + }, + ) + require.NoError(t.t, err) + t.Logf("Funded channel between George and Fabia: %v", fundRespGF) + // Make sure the pending channel shows up in the list and has the // custom records set as JSON. assertPendingChannels( @@ -274,17 +331,21 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, assertPendingChannels( t.t, yaraTap.node, mintedAsset, 1, fundingAmount, 0, ) + assertPendingChannels( + t.t, georgeTap.node, mintedAsset, 1, fundingAmount, 0, + ) // Now that we've looked at the pending channels, let's actually confirm // all three of them. - mineBlocks(t, net, 6, 3) + mineBlocks(t, net, 6, 4) // We'll be tracking the expected asset balances throughout the test, so // we can assert it after each action. - charlieAssetBalance := mintedAsset.Amount - 3*assetSendAmount + charlieAssetBalance := mintedAsset.Amount - 4*assetSendAmount daveAssetBalance := assetSendAmount - fundingAmount erinAssetBalance := assetSendAmount - fundingAmount yaraAssetBalance := assetSendAmount - fundingAmount + georgeAssetBalance := assetSendAmount - fundingAmount itest.AssertBalances( t.t, charlieTap, charlieAssetBalance, @@ -303,6 +364,10 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, t.t, yaraTap, yaraAssetBalance, itest.WithAssetID(assetID), ) + itest.AssertBalances( + t.t, georgeTap, georgeAssetBalance, itest.WithAssetID(assetID), + ) + // Assert that the proofs for both channels has been uploaded to the // designated Universe server. assertUniverseProofExists( @@ -317,6 +382,10 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness, t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes, fmt.Sprintf("%v:%v", fundRespYF.Txid, fundRespYF.OutputIndex), ) + assertUniverseProofExists( + t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes, + fmt.Sprintf("%v:%v", fundRespGF.Txid, fundRespGF.OutputIndex), + ) return nil, nil, nil } @@ -1686,14 +1755,18 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode, sendReq.MaxShardSizeMsat = 80_000_000 } - var rfqBytes []byte + var rfqBytes, peerPubKey []byte cfg.rfq.WhenSome(func(i rfqmsg.ID) { rfqBytes = make([]byte, len(i[:])) copy(rfqBytes, i[:]) }) + if rfqPeer != nil { + peerPubKey = rfqPeer.PubKey[:] + } + request := &tchrpc.SendPaymentRequest{ - PeerPubkey: rfqPeer.PubKey[:], + PeerPubkey: peerPubKey, PaymentRequest: sendReq, RfqId: rfqBytes, AllowOverpay: cfg.allowOverpay, @@ -1732,8 +1805,8 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode, acceptedQuote := quoteMsg.GetAcceptedSellOrder() require.NotNil(t, acceptedQuote) - peerPubKey := acceptedQuote.Peer - require.Equal(t, peerPubKey, rfqPeer.PubKeyStr) + // peerPubKey := acceptedQuote.Peer + // require.Equal(t, peerPubKey, rfqPeer.PubKeyStr) rpcRate := acceptedQuote.BidAssetRate rate, err := rpcutils.UnmarshalRfqFixedPoint(rpcRate) @@ -2548,6 +2621,7 @@ type tapClient struct { rfqrpc.RfqClient tchrpc.TaprootAssetChannelsClient universerpc.UniverseClient + authmailboxrpc.MailboxClient } func newTapClient(t *testing.T, node *HarnessNode) *tapClient { diff --git a/itest/litd_custom_channels_test.go b/itest/litd_custom_channels_test.go index 7a23314fb..0741fea3a 100644 --- a/itest/litd_custom_channels_test.go +++ b/itest/litd_custom_channels_test.go @@ -94,7 +94,30 @@ var ( "not_use_on_mainnet", "--taproot-assets.experimental.rfq.mockoracleassetsperbtc=" + "5820600", + "--taproot-assets.experimental.rfq.acceptpricedeviationppm=50000", }...) + + litdArgsTemplateDiffOracle = []string{ + "--taproot-assets.allow-public-uni-proof-courier", + "--taproot-assets.universe.public-access=rw", + "--taproot-assets.universe.sync-all-assets", + "--taproot-assets.universerpccourier.skipinitdelay", + "--taproot-assets.universerpccourier.backoffresetwait=1s", + "--taproot-assets.universerpccourier.numtries=5", + "--taproot-assets.universerpccourier.initialbackoff=300ms", + "--taproot-assets.universerpccourier.maxbackoff=600ms", + "--taproot-assets.universerpccourier.skipinitdelay", + "--taproot-assets.universerpccourier.backoffresetwait=100ms", + "--taproot-assets.universerpccourier.initialbackoff=300ms", + "--taproot-assets.universerpccourier.maxbackoff=600ms", + "--taproot-assets.custodianproofretrievaldelay=500ms", + "--taproot-assets.experimental.rfq.priceoracleaddress=" + + "use_mock_price_oracle_service_promise_to_" + + "not_use_on_mainnet", + "--taproot-assets.experimental.rfq.mockoracleassetsperbtc=" + + "8820600", + "--taproot-assets.experimental.rfq.acceptpricedeviationppm=50000", + } ) const ( @@ -2971,14 +2994,16 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context, testCustomChannelsLiquidityEdgeCasesCore(ctx, net, t, true) } -// testCustomChannelsMultiRFQReceive tests that a node creating an invoice with -// multiple RFQ quotes can actually guide the payer into using multiple private -// taproot asset channels to pay the invoice. -func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, +// testCustomChannelsMultiRFQ tests that sending and receiving payments works +// when using the multi-rfq features of tapd. This means that liquidity across +// multiple channels and peers can be used to send out a payment, or receive to +// an invoice. +func testCustomChannelsMultiRFQ(ctx context.Context, net *NetworkHarness, t *harnessTest) { lndArgs := slices.Clone(lndArgsTemplate) litdArgs := slices.Clone(litdArgsTemplate) + litdArgsDiffOracle := slices.Clone(litdArgsTemplateDiffOracle) charlie, err := net.NewNode( t.t, "Charlie", lndArgs, false, true, litdArgs..., @@ -2990,6 +3015,11 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, proof.UniverseRpcCourierType, charlie.Cfg.LitAddr(), )) + litdArgsDiffOracle = append(litdArgsDiffOracle, fmt.Sprintf( + "--taproot-assets.proofcourieraddr=%s://%s", + proof.UniverseRpcCourierType, charlie.Cfg.LitAddr(), + )) + dave, err := net.NewNode(t.t, "Dave", lndArgs, false, true, litdArgs...) require.NoError(t.t, err) erin, err := net.NewNode(t.t, "Erin", lndArgs, false, true, litdArgs...) @@ -3002,8 +3032,12 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, t.t, "Yara", lndArgs, false, true, litdArgs..., ) require.NoError(t.t, err) + george, err := net.NewNode( + t.t, "George", lndArgs, false, true, litdArgsDiffOracle..., + ) + require.NoError(t.t, err) - nodes := []*HarnessNode{charlie, dave, erin, fabia, yara} + nodes := []*HarnessNode{charlie, dave, erin, fabia, yara, george} connectAllNodes(t.t, net, nodes) fundAllNodes(t.t, net, nodes) @@ -3013,6 +3047,7 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, erinTap := newTapClient(t.t, erin) fabiaTap := newTapClient(t.t, fabia) yaraTap := newTapClient(t.t, yara) + georgeTap := newTapClient(t.t, george) assetReq := itest.CopyRequest(&mintrpc.MintAssetRequest{ Asset: itestAsset, @@ -3030,7 +3065,7 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, assetID := cents.AssetGenesis.AssetId groupID := cents.GetAssetGroup().GetTweakedGroupKey() - syncUniverses(t.t, charlieTap, dave, erin, fabia, yara) + syncUniverses(t.t, charlieTap, dave, erin, fabia, yara, george) multiRfqNodes := multiRfqNodes{ charlie: itestNode{ @@ -3053,6 +3088,10 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, Lnd: yara, Tapd: yaraTap, }, + george: itestNode{ + Lnd: george, + Tapd: georgeTap, + }, universeTap: charlieTap, } @@ -3068,7 +3107,6 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, t.t, charlie, &lnrpc.AddInvoiceResponse{ PaymentRequest: hodlInv.payReq, }, - withGroupKey(groupID), withFailure(lnrpc.Payment_IN_FLIGHT, failureNone), ) @@ -3100,13 +3138,88 @@ func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, // Now let's create a normal invoice that will be settled once all the // HTLCs have been received. This is only possible because the payer // uses multiple bolt11 hop hints to reach the destination. - invoiceResp := createAssetInvoice(t.t, nil, fabia, 15_000, assetID) + invoiceResp := createAssetInvoice( + t.t, nil, fabia, 15_000, nil, withInvGroupKey(groupID), + ) payInvoiceWithSatoshi( - t.t, charlie, invoiceResp, withGroupKey(groupID), + t.t, charlie, invoiceResp, ) logBalance(t.t, nodes, assetID, "after multi-rfq receive") + + // Now we'll test that sending with multiple rfq quotes works. + + // Let's start by providing some liquidity to Charlie's peers, in order + // for them to be able to push some amount if Fabia picks them as part + // of the route. + sendKeySendPayment(t.t, charlie, erin, 800_000) + sendKeySendPayment(t.t, charlie, dave, 800_000) + sendKeySendPayment(t.t, charlie, yara, 800_000) + + // Let's ask for the rough equivalent of ~15k assets. Fabia, who's going + // to pay the invoice, only has parts of assets that are less than 10k + // in channels with one of the 3 intermediate peers. The only way to + // pay this invoice is by splitting the payment across multiple peers by + // using multiple RFQ quotes. + invAmt := int64(15_000 * 17) + + iResp, err := charlie.AddHoldInvoice( + ctx, &invoicesrpc.AddHoldInvoiceRequest{ + Memo: "", + Value: invAmt, + Hash: payHash[:], + }, + ) + require.NoError(t.t, err) + + payReq := iResp.PaymentRequest + + payInvoiceWithAssets( + t.t, fabia, nil, payReq, assetID, + withFailure(lnrpc.Payment_IN_FLIGHT, failureNone), + ) + + assertMinNumHtlcs(t.t, charlie, 2) + assertMinNumHtlcs(t.t, fabia, 2) + + logBalance(t.t, nodes, assetID, "multi-rfq send in-flight") + + _, err = charlie.SettleInvoice(ctx, &invoicesrpc.SettleInvoiceMsg{ + Preimage: hodlInv.preimage[:], + }) + require.NoError(t.t, err) + + assertNumHtlcs(t.t, charlie, 0) + assertNumHtlcs(t.t, fabia, 0) + + logBalance(t.t, nodes, assetID, "after multi-rfq send") + + // Let's make another round-trip involving multi-rfq functionality. + // Let's have Fabia receive another large payment and send it back + // again, this time with a greater amount. + invoiceResp = createAssetInvoice(t.t, nil, fabia, 25_000, assetID) + + payInvoiceWithSatoshi( + t.t, charlie, invoiceResp, + ) + + logBalance(t.t, nodes, assetID, "after multi-rfq receive (2nd)") + + // Let's bump up the invoice amount a bit, to roughly ~22k assets. + invAmt = 22_000 * 17 + inv, err := charlie.AddInvoice(ctx, &lnrpc.Invoice{ + Value: invAmt, + }) + require.NoError(t.t, err) + + payReq = inv.PaymentRequest + + payInvoiceWithAssets( + t.t, fabia, nil, payReq, nil, withGroupKey(groupID), + ) + + logBalance(t.t, nodes, assetID, "after multi-rfq send (2nd)") } // testCustomChannelsStrictForwarding is a test that tests the strict forwarding diff --git a/itest/litd_test_list_on_test.go b/itest/litd_test_list_on_test.go index 36685b0ab..9d5e325ec 100644 --- a/itest/litd_test_list_on_test.go +++ b/itest/litd_test_list_on_test.go @@ -130,8 +130,11 @@ var allTestCases = []*testCase{ }, { name: "custom channels multi rfq", - test: testCustomChannelsMultiRFQReceive, + test: testCustomChannelsMultiRFQ, noAliceBob: true, + backwardCompat: map[string]string{ + "Yara": "v0.15.0-alpha", + }, }, { name: "custom channels multi channel pathfinding",