@@ -77,25 +77,32 @@ type itestNode struct {
7777// multiRfqNodes contains all the itest nodes that are required to set up the 
7878// multi RFQ network topology. 
7979type  multiRfqNodes  struct  {
80- 	charlie , dave , erin , fabia , yara  itestNode 
81- 	universeTap                       * tapClient 
80+ 	charlie , dave , erin , fabia , yara ,  george  itestNode 
81+ 	universeTap                                * tapClient 
8282}
8383
8484// createTestMultiRFQAssetNetwork creates a lightning network topology which 
8585// consists of both bitcoin and asset channels. It focuses on the property of 
8686// having multiple channels available on both the sender and receiver side. 
87+ // The George node is using a way different oracle that provides asset rates 
88+ // that fall outside of the configured tolerance bounds, leading to RFQ 
89+ // negotiation failures. 
8790// 
8891// The topology we are going for looks like the following: 
8992// 
90- //	  /---[sats]--> Erin --[assets]--\ 
91- //	 /                                \ 
92- //	/                                  \ 
93+ //	   /---[sats]--> Erin --[assets]--\ 
94+ //	  /                                \ 
95+ //	 /                                  \ 
96+ //	/                                    \ 
9397// 
94- // Charlie  -----[sats]-->   Dave   --[assets]----> Fabia 
98+ // Charlie  -----[sats]--> Dave --[assets]-->  Fabia 
9599// 
96- //	\                                  / 
97- //	 \                                / 
98- //	  \---[sats]--> Yara --[assets]--/ 
100+ //	\                                     / / 
101+ //	 \                                   / / 
102+ //	  \---[sats]--> Yara --[assets]-----/ / 
103+ //	   \                                 / 
104+ //	    \                               / 
105+ //	     \--[sats]-> George --[assets]-/ 
99106func  createTestMultiRFQAssetNetwork (t  * harnessTest , net  * NetworkHarness ,
100107	nodes  multiRfqNodes , mintedAsset  * taprpc.Asset , assetSendAmount ,
101108	fundingAmount  uint64 , pushSat  int64 ) (* lnrpc.ChannelPoint ,
@@ -106,6 +113,7 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
106113	erin , erinTap  :=  nodes .erin .Lnd , nodes .erin .Tapd 
107114	_ , fabiaTap  :=  nodes .fabia .Lnd , nodes .fabia .Tapd 
108115	yara , yaraTap  :=  nodes .yara .Lnd , nodes .yara .Tapd 
116+ 	george , georgeTap  :=  nodes .george .Lnd , nodes .george .Tapd 
109117	universeTap  :=  nodes .universeTap 
110118
111119	// Let's open the normal sats channels between Charlie and the routing 
@@ -131,6 +139,13 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
131139		},
132140	)
133141
142+ 	_  =  openChannelAndAssert (
143+ 		t , net , charlie , george , lntest.OpenChannelParams {
144+ 			Amt :         10_000_000 ,
145+ 			SatPerVByte : 5 ,
146+ 		},
147+ 	)
148+ 
134149	ctxb  :=  context .Background ()
135150	assetID  :=  mintedAsset .AssetGenesis .AssetId 
136151	var  groupKey  []byte 
@@ -225,6 +240,34 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
225240	)
226241	itest .AssertNonInteractiveRecvComplete (t .t , yaraTap , 1 )
227242
243+ 	// We need to send some assets to George, so he can fund an asset 
244+ 	// channel with Fabia. 
245+ 	georgeAddr , err  :=  georgeTap .NewAddr (ctxb , & taprpc.NewAddrRequest {
246+ 		Amt :     assetSendAmount ,
247+ 		AssetId : assetID ,
248+ 		ProofCourierAddr : fmt .Sprintf (
249+ 			"%s://%s" , proof .UniverseRpcCourierType ,
250+ 			charlieTap .node .Cfg .LitAddr (),
251+ 		),
252+ 	})
253+ 	require .NoError (t .t , err )
254+ 
255+ 	t .Logf ("Sending %v asset units to George..." , assetSendAmount )
256+ 
257+ 	// Send the assets to George. 
258+ 	itest .AssertAddrCreated (t .t , georgeTap , mintedAsset , georgeAddr )
259+ 	sendResp , err  =  charlieTap .SendAsset (ctxb , & taprpc.SendAssetRequest {
260+ 		TapAddrs : []string {georgeAddr .Encoded },
261+ 	})
262+ 	require .NoError (t .t , err )
263+ 	itest .ConfirmAndAssertOutboundTransfer (
264+ 		t .t , t .lndHarness .Miner .Client , charlieTap , sendResp , assetID ,
265+ 		[]uint64 {
266+ 			mintedAsset .Amount  -  4 * assetSendAmount , assetSendAmount ,
267+ 		}, 3 , 4 ,
268+ 	)
269+ 	itest .AssertNonInteractiveRecvComplete (t .t , georgeTap , 1 )
270+ 
228271	// We fund the Dave->Fabia channel. 
229272	fundRespDF , err  :=  daveTap .FundChannel (
230273		ctxb , & tchrpc.FundChannelRequest {
@@ -264,6 +307,19 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
264307	require .NoError (t .t , err )
265308	t .Logf ("Funded channel between Yara and Fabia: %v" , fundRespYF )
266309
310+ 	// We fund the George->Fabia channel. 
311+ 	fundRespGF , err  :=  georgeTap .FundChannel (
312+ 		ctxb , & tchrpc.FundChannelRequest {
313+ 			AssetAmount :        fundingAmount ,
314+ 			AssetId :            assetID ,
315+ 			PeerPubkey :         fabiaTap .node .PubKey [:],
316+ 			FeeRateSatPerVbyte : 5 ,
317+ 			PushSat :            pushSat ,
318+ 		},
319+ 	)
320+ 	require .NoError (t .t , err )
321+ 	t .Logf ("Funded channel between George and Fabia: %v" , fundRespGF )
322+ 
267323	// Make sure the pending channel shows up in the list and has the 
268324	// custom records set as JSON. 
269325	assertPendingChannels (
@@ -275,17 +331,21 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
275331	assertPendingChannels (
276332		t .t , yaraTap .node , mintedAsset , 1 , fundingAmount , 0 ,
277333	)
334+ 	assertPendingChannels (
335+ 		t .t , georgeTap .node , mintedAsset , 1 , fundingAmount , 0 ,
336+ 	)
278337
279338	// Now that we've looked at the pending channels, let's actually confirm 
280339	// all three of them. 
281- 	mineBlocks (t , net , 6 , 3 )
340+ 	mineBlocks (t , net , 6 , 4 )
282341
283342	// We'll be tracking the expected asset balances throughout the test, so 
284343	// we can assert it after each action. 
285- 	charlieAssetBalance  :=  mintedAsset .Amount  -  3 * assetSendAmount 
344+ 	charlieAssetBalance  :=  mintedAsset .Amount  -  4 * assetSendAmount 
286345	daveAssetBalance  :=  assetSendAmount  -  fundingAmount 
287346	erinAssetBalance  :=  assetSendAmount  -  fundingAmount 
288347	yaraAssetBalance  :=  assetSendAmount  -  fundingAmount 
348+ 	georgeAssetBalance  :=  assetSendAmount  -  fundingAmount 
289349
290350	itest .AssertBalances (
291351		t .t , charlieTap , charlieAssetBalance ,
@@ -304,6 +364,10 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
304364		t .t , yaraTap , yaraAssetBalance , itest .WithAssetID (assetID ),
305365	)
306366
367+ 	itest .AssertBalances (
368+ 		t .t , georgeTap , georgeAssetBalance , itest .WithAssetID (assetID ),
369+ 	)
370+ 
307371	// Assert that the proofs for both channels has been uploaded to the 
308372	// designated Universe server. 
309373	assertUniverseProofExists (
@@ -318,6 +382,10 @@ func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
318382		t .t , universeTap , assetID , groupKey , fundingScriptTreeBytes ,
319383		fmt .Sprintf ("%v:%v" , fundRespYF .Txid , fundRespYF .OutputIndex ),
320384	)
385+ 	assertUniverseProofExists (
386+ 		t .t , universeTap , assetID , groupKey , fundingScriptTreeBytes ,
387+ 		fmt .Sprintf ("%v:%v" , fundRespGF .Txid , fundRespGF .OutputIndex ),
388+ 	)
321389
322390	return  nil , nil , nil 
323391}
@@ -1355,7 +1423,7 @@ func sendAssetKeySendPayment(t *testing.T, src, dst *HarnessNode, amt uint64,
13551423		return 
13561424	}
13571425
1358- 	result , err  :=  getAssetPaymentResult (stream , false )
1426+ 	result , _ ,  err  :=  getAssetPaymentResult (t ,  stream , false )
13591427	require .NoError (t , err )
13601428	if  result .Status  ==  lnrpc .Payment_FAILED  {
13611429		t .Logf ("Failure reason: %v" , result .FailureReason )
@@ -1687,14 +1755,18 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
16871755		sendReq .MaxShardSizeMsat  =  80_000_000 
16881756	}
16891757
1690- 	var  rfqBytes  []byte 
1758+ 	var  rfqBytes ,  peerPubKey  []byte 
16911759	cfg .rfq .WhenSome (func (i  rfqmsg.ID ) {
16921760		rfqBytes  =  make ([]byte , len (i [:]))
16931761		copy (rfqBytes , i [:])
16941762	})
16951763
1764+ 	if  rfqPeer  !=  nil  {
1765+ 		peerPubKey  =  rfqPeer .PubKey [:]
1766+ 	}
1767+ 
16961768	request  :=  & tchrpc.SendPaymentRequest {
1697- 		PeerPubkey :     rfqPeer . PubKey [:] ,
1769+ 		PeerPubkey :     peerPubKey ,
16981770		PaymentRequest : sendReq ,
16991771		RfqId :          rfqBytes ,
17001772		AllowOverpay :   cfg .allowOverpay ,
@@ -1715,7 +1787,13 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
17151787	// was established, no network or auth error), we expect the error to be 
17161788	// returned on the first read on the stream. 
17171789	if  cfg .errSubStr  !=  ""  {
1718- 		_ , err  :=  stream .Recv ()
1790+ 		msg , err  :=  stream .Recv ()
1791+ 
1792+ 		// On errors we still get an empty set of RFQs as a response. 
1793+ 		if  msg .GetAcceptedSellOrders () !=  nil  {
1794+ 			_ , err  =  stream .Recv ()
1795+ 		}
1796+ 
17191797		require .ErrorContains (t , err , cfg .errSubStr )
17201798
17211799		return  0 , rfqmath.BigIntFixedPoint {}
@@ -1725,42 +1803,18 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
17251803		numUnits  uint64 
17261804		rateVal   rfqmath.FixedPoint [rfqmath.BigInt ]
17271805	)
1728- 	if  cfg .rfq .IsNone () {
1729- 		// We want to receive the accepted quote message first, so we 
1730- 		// know how many assets we're going to pay. 
1731- 		quoteMsg , err  :=  stream .Recv ()
1732- 		require .NoError (t , err )
1733- 		acceptedQuote  :=  quoteMsg .GetAcceptedSellOrder ()
1734- 		require .NotNil (t , acceptedQuote )
1735- 
1736- 		peerPubKey  :=  acceptedQuote .Peer 
1737- 		require .Equal (t , peerPubKey , rfqPeer .PubKeyStr )
1738- 
1739- 		rpcRate  :=  acceptedQuote .BidAssetRate 
1740- 		rate , err  :=  rpcutils .UnmarshalRfqFixedPoint (rpcRate )
1741- 		require .NoError (t , err )
1742- 
1743- 		rateVal  =  * rate 
17441806
1745- 		t .Logf ("Got quote for %v asset units per BTC" , rate )
1746- 
1747- 		amountMsat  :=  lnwire .MilliSatoshi (decodedInvoice .NumMsat )
1748- 		milliSatsFP  :=  rfqmath .MilliSatoshiToUnits (amountMsat , * rate )
1749- 		numUnits  =  milliSatsFP .ScaleTo (0 ).ToUint64 ()
1750- 		msatPerUnit  :=  float64 (decodedInvoice .NumMsat ) / 
1751- 			float64 (numUnits )
1752- 		t .Logf ("Got quote for %v asset units at %3f msat/unit from " + 
1753- 			"peer %s with SCID %d" , numUnits , msatPerUnit ,
1754- 			peerPubKey , acceptedQuote .Scid )
1755- 	}
1756- 
1757- 	result , err  :=  getAssetPaymentResult (
1758- 		stream , cfg .payStatus  ==  lnrpc .Payment_IN_FLIGHT ,
1807+ 	result , rateVal , err  :=  getAssetPaymentResult (
1808+ 		t , stream , cfg .payStatus  ==  lnrpc .Payment_IN_FLIGHT ,
17591809	)
17601810	require .NoError (t , err )
17611811	require .Equal (t , cfg .payStatus , result .Status )
17621812	require .Equal (t , cfg .failureReason , result .FailureReason )
17631813
1814+ 	amountMsat  :=  lnwire .MilliSatoshi (decodedInvoice .NumMsat )
1815+ 	milliSatsFP  :=  rfqmath .MilliSatoshiToUnits (amountMsat , rateVal )
1816+ 	numUnits  =  milliSatsFP .ScaleTo (0 ).ToUint64 ()
1817+ 
17641818	return  numUnits , rateVal 
17651819}
17661820
0 commit comments