Skip to content

Commit 51e4b2c

Browse files
committed
itest: add multi-rfq asset network creator
1 parent 76ea00b commit 51e4b2c

File tree

1 file changed

+237
-0
lines changed

1 file changed

+237
-0
lines changed

itest/assets_test.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
3939
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
4040
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
41+
"github.com/lightningnetwork/lnd/lntest"
4142
"github.com/lightningnetwork/lnd/lntest/rpc"
4243
"github.com/lightningnetwork/lnd/lntest/wait"
4344
"github.com/lightningnetwork/lnd/lntypes"
@@ -66,6 +67,242 @@ var (
6667
failureNone = lnrpc.PaymentFailureReason_FAILURE_REASON_NONE
6768
)
6869

70+
// createTestMultiRFQAssetNetwork creates a lightning network topology which
71+
// consists of both bitcoin and asset channels. It focuses on the property of
72+
// having multiple channels available on both the sender and receiver side.
73+
//
74+
// The topology we are going for looks like the following:
75+
//
76+
// /---[sats]--> Erin --[assets]--\
77+
// / \
78+
// / \
79+
//
80+
// Charlie -----[sats]--> Dave --[assets]---->Fabia
81+
//
82+
// \ /
83+
// \ /
84+
// \---[sats]--> Yara --[assets]--/
85+
func createTestMultiRFQAssetNetwork(t *harnessTest, net *NetworkHarness,
86+
charlie, dave, erin, fabia, yara *HarnessNode, charlieTap, daveTap,
87+
erinTap, fabiaTap, yaraTap, universeTap *tapClient,
88+
mintedAsset *taprpc.Asset, assetSendAmount, fundingAmount uint64,
89+
pushSat int64) (*lnrpc.ChannelPoint, *lnrpc.ChannelPoint,
90+
*lnrpc.ChannelPoint) {
91+
92+
// Let's open the normal sats channels between Charlie and the routing
93+
// peers.
94+
_ = openChannelAndAssert(
95+
t, net, charlie, erin, lntest.OpenChannelParams{
96+
Amt: 10_000_000,
97+
SatPerVByte: 5,
98+
},
99+
)
100+
101+
_ = openChannelAndAssert(
102+
t, net, charlie, dave, lntest.OpenChannelParams{
103+
Amt: 10_000_000,
104+
SatPerVByte: 5,
105+
},
106+
)
107+
108+
_ = openChannelAndAssert(
109+
t, net, charlie, yara, lntest.OpenChannelParams{
110+
Amt: 10_000_000,
111+
SatPerVByte: 5,
112+
},
113+
)
114+
115+
ctxb := context.Background()
116+
assetID := mintedAsset.AssetGenesis.AssetId
117+
var groupKey []byte
118+
if mintedAsset.AssetGroup != nil {
119+
groupKey = mintedAsset.AssetGroup.TweakedGroupKey
120+
}
121+
122+
fundingScriptTree := tapscript.NewChannelFundingScriptTree()
123+
fundingScriptKey := fundingScriptTree.TaprootKey
124+
fundingScriptTreeBytes := fundingScriptKey.SerializeCompressed()
125+
126+
// We need to send some assets to Dave, so he can fund an asset channel
127+
// with Fabia.
128+
daveAddr, err := daveTap.NewAddr(ctxb, &taprpc.NewAddrRequest{
129+
Amt: assetSendAmount,
130+
AssetId: assetID,
131+
ProofCourierAddr: fmt.Sprintf(
132+
"%s://%s", proof.UniverseRpcCourierType,
133+
charlieTap.node.Cfg.LitAddr(),
134+
),
135+
})
136+
require.NoError(t.t, err)
137+
138+
t.Logf("Sending %v asset units to Dave...", assetSendAmount)
139+
140+
// Send the assets to Dave.
141+
itest.AssertAddrCreated(t.t, daveTap, mintedAsset, daveAddr)
142+
sendResp, err := charlieTap.SendAsset(ctxb, &taprpc.SendAssetRequest{
143+
TapAddrs: []string{daveAddr.Encoded},
144+
})
145+
require.NoError(t.t, err)
146+
itest.ConfirmAndAssertOutboundTransfer(
147+
t.t, t.lndHarness.Miner.Client, charlieTap, sendResp, assetID,
148+
[]uint64{mintedAsset.Amount - assetSendAmount, assetSendAmount},
149+
0, 1,
150+
)
151+
itest.AssertNonInteractiveRecvComplete(t.t, daveTap, 1)
152+
153+
// We need to send some assets to Erin, so he can fund an asset channel
154+
// with Fabia.
155+
erinAddr, err := erinTap.NewAddr(ctxb, &taprpc.NewAddrRequest{
156+
Amt: assetSendAmount,
157+
AssetId: assetID,
158+
ProofCourierAddr: fmt.Sprintf(
159+
"%s://%s", proof.UniverseRpcCourierType,
160+
charlieTap.node.Cfg.LitAddr(),
161+
),
162+
})
163+
require.NoError(t.t, err)
164+
165+
t.Logf("Sending %v asset units to Erin...", assetSendAmount)
166+
167+
// Send the assets to Erin.
168+
itest.AssertAddrCreated(t.t, erinTap, mintedAsset, erinAddr)
169+
sendResp, err = charlieTap.SendAsset(ctxb, &taprpc.SendAssetRequest{
170+
TapAddrs: []string{erinAddr.Encoded},
171+
})
172+
require.NoError(t.t, err)
173+
itest.ConfirmAndAssertOutboundTransfer(
174+
t.t, t.lndHarness.Miner.Client, charlieTap, sendResp, assetID,
175+
[]uint64{
176+
mintedAsset.Amount - 2*assetSendAmount, assetSendAmount,
177+
}, 1, 2,
178+
)
179+
itest.AssertNonInteractiveRecvComplete(t.t, erinTap, 1)
180+
181+
// We need to send some assets to Yara, so he can fund an asset channel
182+
// with Fabia.
183+
yaraAddr, err := yaraTap.NewAddr(ctxb, &taprpc.NewAddrRequest{
184+
Amt: assetSendAmount,
185+
AssetId: assetID,
186+
ProofCourierAddr: fmt.Sprintf(
187+
"%s://%s", proof.UniverseRpcCourierType,
188+
charlieTap.node.Cfg.LitAddr(),
189+
),
190+
})
191+
require.NoError(t.t, err)
192+
193+
t.Logf("Sending %v asset units to Yara...", assetSendAmount)
194+
195+
// Send the assets to Yara.
196+
itest.AssertAddrCreated(t.t, yaraTap, mintedAsset, yaraAddr)
197+
sendResp, err = charlieTap.SendAsset(ctxb, &taprpc.SendAssetRequest{
198+
TapAddrs: []string{yaraAddr.Encoded},
199+
})
200+
require.NoError(t.t, err)
201+
itest.ConfirmAndAssertOutboundTransfer(
202+
t.t, t.lndHarness.Miner.Client, charlieTap, sendResp, assetID,
203+
[]uint64{
204+
mintedAsset.Amount - 3*assetSendAmount, assetSendAmount,
205+
}, 2, 3,
206+
)
207+
itest.AssertNonInteractiveRecvComplete(t.t, yaraTap, 1)
208+
209+
// We fund the Dave->Fabia channel.
210+
fundRespDF, err := daveTap.FundChannel(
211+
ctxb, &tchrpc.FundChannelRequest{
212+
AssetAmount: fundingAmount,
213+
AssetId: assetID,
214+
PeerPubkey: fabiaTap.node.PubKey[:],
215+
FeeRateSatPerVbyte: 5,
216+
PushSat: pushSat,
217+
},
218+
)
219+
require.NoError(t.t, err)
220+
t.Logf("Funded channel between Dave and Fabia: %v", fundRespDF)
221+
222+
// We fund the Erin->Fabia channel.
223+
fundRespEF, err := erinTap.FundChannel(
224+
ctxb, &tchrpc.FundChannelRequest{
225+
AssetAmount: fundingAmount,
226+
AssetId: assetID,
227+
PeerPubkey: fabiaTap.node.PubKey[:],
228+
FeeRateSatPerVbyte: 5,
229+
PushSat: pushSat,
230+
},
231+
)
232+
require.NoError(t.t, err)
233+
t.Logf("Funded channel between Erin and Fabia: %v", fundRespEF)
234+
235+
// We fund the Yara->Fabia channel.
236+
fundRespYF, err := yaraTap.FundChannel(
237+
ctxb, &tchrpc.FundChannelRequest{
238+
AssetAmount: fundingAmount,
239+
AssetId: assetID,
240+
PeerPubkey: fabiaTap.node.PubKey[:],
241+
FeeRateSatPerVbyte: 5,
242+
PushSat: pushSat,
243+
},
244+
)
245+
require.NoError(t.t, err)
246+
t.Logf("Funded channel between Yara and Fabia: %v", fundRespYF)
247+
248+
// Make sure the pending channel shows up in the list and has the
249+
// custom records set as JSON.
250+
assertPendingChannels(
251+
t.t, daveTap.node, mintedAsset, 1, fundingAmount, 0,
252+
)
253+
assertPendingChannels(
254+
t.t, erinTap.node, mintedAsset, 1, fundingAmount, 0,
255+
)
256+
assertPendingChannels(
257+
t.t, yaraTap.node, mintedAsset, 1, fundingAmount, 0,
258+
)
259+
260+
// Now that we've looked at the pending channels, let's actually confirm
261+
// all three of them.
262+
mineBlocks(t, net, 6, 3)
263+
264+
// We'll be tracking the expected asset balances throughout the test, so
265+
// we can assert it after each action.
266+
charlieAssetBalance := mintedAsset.Amount - 3*assetSendAmount
267+
daveAssetBalance := assetSendAmount - fundingAmount
268+
erinAssetBalance := assetSendAmount - fundingAmount
269+
yaraAssetBalance := assetSendAmount - fundingAmount
270+
271+
itest.AssertBalances(
272+
t.t, charlieTap, charlieAssetBalance,
273+
itest.WithAssetID(assetID), itest.WithNumUtxos(1),
274+
)
275+
276+
itest.AssertBalances(
277+
t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID),
278+
)
279+
280+
itest.AssertBalances(
281+
t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID),
282+
)
283+
284+
itest.AssertBalances(
285+
t.t, yaraTap, yaraAssetBalance, itest.WithAssetID(assetID),
286+
)
287+
288+
// Assert that the proofs for both channels has been uploaded to the
289+
// designated Universe server.
290+
assertUniverseProofExists(
291+
t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes,
292+
fmt.Sprintf("%v:%v", fundRespDF.Txid, fundRespDF.OutputIndex),
293+
)
294+
assertUniverseProofExists(
295+
t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes,
296+
fmt.Sprintf("%v:%v", fundRespEF.Txid, fundRespEF.OutputIndex),
297+
)
298+
assertUniverseProofExists(
299+
t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes,
300+
fmt.Sprintf("%v:%v", fundRespYF.Txid, fundRespYF.OutputIndex),
301+
)
302+
303+
return nil, nil, nil
304+
}
305+
69306
// createTestAssetNetwork sends asset funds from Charlie to Dave and Erin, so
70307
// they can fund asset channels with Yara and Fabia, respectively. So the asset
71308
// channels created are Charlie->Dave, Dave->Yara, Erin->Fabia. The channels

0 commit comments

Comments
 (0)