|
48 | 48 | AssetType: taprpc.AssetType_NORMAL, |
49 | 49 | Name: "itest-asset-cents", |
50 | 50 | AssetMeta: dummyMetaData, |
51 | | - Amount: 1_000_000, |
| 51 | + Amount: 10_000_000, |
52 | 52 | } |
53 | 53 |
|
54 | 54 | shortTimeout = time.Second * 5 |
@@ -2720,14 +2720,15 @@ func testCustomChannelsLiquidtyEdgeCasesCore(ctx context.Context, |
2720 | 2720 | t.Logf("Universes synced between all nodes, distributing assets...") |
2721 | 2721 |
|
2722 | 2722 | const ( |
2723 | | - daveFundingAmount = uint64(400_000) |
2724 | | - erinFundingAmount = uint64(200_000) |
| 2723 | + daveFundingAmount = uint64(400_000) |
| 2724 | + erinFundingAmount = uint64(200_000) |
| 2725 | + charlieFundingAmount = uint64(400_000) |
2725 | 2726 | ) |
2726 | | - charlieFundingAmount := cents.Amount - uint64(2*400_000) |
| 2727 | + // charlieFundingAmount := cents.Amount - uint64(2*400_000) |
2727 | 2728 |
|
2728 | 2729 | _, _, _ = createTestAssetNetwork( |
2729 | 2730 | t, net, charlieTap, daveTap, erinTap, fabiaTap, yaraTap, |
2730 | | - universeTap, cents, 400_000, charlieFundingAmount, |
| 2731 | + universeTap, cents, 500_000, charlieFundingAmount, |
2731 | 2732 | daveFundingAmount, erinFundingAmount, 0, |
2732 | 2733 | ) |
2733 | 2734 |
|
@@ -3126,6 +3127,160 @@ func testCustomChannelsLiquidityEdgeCasesGroup(ctx context.Context, |
3126 | 3127 | testCustomChannelsLiquidtyEdgeCasesCore(ctx, net, t, true) |
3127 | 3128 | } |
3128 | 3129 |
|
| 3130 | +// testCustomChannelsMultiRFQReceive tests that a node creating an invoice with |
| 3131 | +// multiple RFQ quotes can actually guide the payer into using multiple private |
| 3132 | +// taproot asset channels to pay the invoice. |
| 3133 | +func testCustomChannelsMultiRFQReceive(ctx context.Context, net *NetworkHarness, |
| 3134 | + t *harnessTest) { |
| 3135 | + |
| 3136 | + lndArgs := slices.Clone(lndArgsTemplate) |
| 3137 | + litdArgs := slices.Clone(litdArgsTemplate) |
| 3138 | + |
| 3139 | + // Explicitly set the proof courier as Zane (now has no other role |
| 3140 | + // other than proof shuffling), otherwise a hashmail courier will be |
| 3141 | + // used. For the funding transaction, we're just posting it and don't |
| 3142 | + // expect a true receiver. |
| 3143 | + zane, err := net.NewNode( |
| 3144 | + t.t, "Zane", lndArgs, false, true, litdArgs..., |
| 3145 | + ) |
| 3146 | + require.NoError(t.t, err) |
| 3147 | + |
| 3148 | + litdArgs = append(litdArgs, fmt.Sprintf( |
| 3149 | + "--taproot-assets.proofcourieraddr=%s://%s", |
| 3150 | + proof.UniverseRpcCourierType, zane.Cfg.LitAddr(), |
| 3151 | + )) |
| 3152 | + |
| 3153 | + charlie, err := net.NewNode( |
| 3154 | + t.t, "Charlie", lndArgs, false, true, litdArgs..., |
| 3155 | + ) |
| 3156 | + require.NoError(t.t, err) |
| 3157 | + |
| 3158 | + dave, err := net.NewNode(t.t, "Dave", lndArgs, false, true, litdArgs...) |
| 3159 | + require.NoError(t.t, err) |
| 3160 | + erin, err := net.NewNode(t.t, "Erin", lndArgs, false, true, litdArgs...) |
| 3161 | + require.NoError(t.t, err) |
| 3162 | + fabia, err := net.NewNode( |
| 3163 | + t.t, "Fabia", lndArgs, false, true, litdArgs..., |
| 3164 | + ) |
| 3165 | + require.NoError(t.t, err) |
| 3166 | + yara, err := net.NewNode( |
| 3167 | + t.t, "Yara", lndArgs, false, true, litdArgs..., |
| 3168 | + ) |
| 3169 | + require.NoError(t.t, err) |
| 3170 | + |
| 3171 | + nodes := []*HarnessNode{charlie, dave, erin, fabia, yara} |
| 3172 | + connectAllNodes(t.t, net, nodes) |
| 3173 | + fundAllNodes(t.t, net, nodes) |
| 3174 | + |
| 3175 | + // The topology we are going for looks like the following: |
| 3176 | + // |
| 3177 | + // /---[sats]--> Erin --[assets]--\ |
| 3178 | + // / \ |
| 3179 | + // / \ |
| 3180 | + // Charlie -----[sats]--> Dave --[assets]---->Fabia |
| 3181 | + // \ / |
| 3182 | + // \ / |
| 3183 | + // \---[sats]--> Yara --[assets]--/ |
| 3184 | + // |
| 3185 | + |
| 3186 | + // Let's open the normal sats channels between Charlie and the routing |
| 3187 | + // peers. |
| 3188 | + _ = openChannelAndAssert( |
| 3189 | + t, net, charlie, erin, lntest.OpenChannelParams{ |
| 3190 | + Amt: 10_000_000, |
| 3191 | + SatPerVByte: 5, |
| 3192 | + }, |
| 3193 | + ) |
| 3194 | + |
| 3195 | + _ = openChannelAndAssert( |
| 3196 | + t, net, charlie, dave, lntest.OpenChannelParams{ |
| 3197 | + Amt: 10_000_000, |
| 3198 | + SatPerVByte: 5, |
| 3199 | + }, |
| 3200 | + ) |
| 3201 | + |
| 3202 | + _ = openChannelAndAssert( |
| 3203 | + t, net, charlie, yara, lntest.OpenChannelParams{ |
| 3204 | + Amt: 10_000_000, |
| 3205 | + SatPerVByte: 5, |
| 3206 | + }, |
| 3207 | + ) |
| 3208 | + |
| 3209 | + // Let's create the tap clients. |
| 3210 | + universeTap := newTapClient(t.t, zane) |
| 3211 | + charlieTap := newTapClient(t.t, charlie) |
| 3212 | + daveTap := newTapClient(t.t, dave) |
| 3213 | + erinTap := newTapClient(t.t, erin) |
| 3214 | + fabiaTap := newTapClient(t.t, fabia) |
| 3215 | + yaraTap := newTapClient(t.t, yara) |
| 3216 | + |
| 3217 | + assetReq := itest.CopyRequest(&mintrpc.MintAssetRequest{ |
| 3218 | + Asset: itestAsset, |
| 3219 | + }) |
| 3220 | + |
| 3221 | + assetReq.Asset.NewGroupedAsset = true |
| 3222 | + |
| 3223 | + // Mint an asset on Charlie and sync all nodes to Charlie as the |
| 3224 | + // universe. |
| 3225 | + mintedAssets := itest.MintAssetsConfirmBatch( |
| 3226 | + t.t, t.lndHarness.Miner.Client, charlieTap, |
| 3227 | + []*mintrpc.MintAssetRequest{assetReq}, |
| 3228 | + ) |
| 3229 | + cents := mintedAssets[0] |
| 3230 | + assetID := cents.AssetGenesis.AssetId |
| 3231 | + groupID := cents.GetAssetGroup().GetTweakedGroupKey() |
| 3232 | + |
| 3233 | + syncUniverses(t.t, charlieTap, dave, erin, fabia, yara) |
| 3234 | + |
| 3235 | + createTestMultiRFQAssetNetwork( |
| 3236 | + t, net, charlieTap, daveTap, erinTap, fabiaTap, yaraTap, |
| 3237 | + universeTap, cents, 10_000, 10_000, 10_000, |
| 3238 | + ) |
| 3239 | + |
| 3240 | + logBalance(t.t, nodes, assetID, "before multi-rfq receive") |
| 3241 | + |
| 3242 | + hodlInv := createAssetHodlInvoice(t.t, nil, fabia, 20_000, assetID) |
| 3243 | + |
| 3244 | + payInvoiceWithSatoshi( |
| 3245 | + t.t, charlie, &lnrpc.AddInvoiceResponse{ |
| 3246 | + PaymentRequest: hodlInv.payReq, |
| 3247 | + }, |
| 3248 | + withGroupKey(groupID), |
| 3249 | + withFailure(lnrpc.Payment_IN_FLIGHT, failureNone), |
| 3250 | + ) |
| 3251 | + |
| 3252 | + logBalance(t.t, nodes, assetID, "after inflight multi-rfq") |
| 3253 | + |
| 3254 | + // TODO: assert minNumHtlcs after rebase |
| 3255 | + |
| 3256 | + // Now let's cancel the invoice and assert that all inbound channels |
| 3257 | + // have cleared their HTLCs. |
| 3258 | + payHash := hodlInv.preimage.Hash() |
| 3259 | + _, err = fabia.InvoicesClient.CancelInvoice( |
| 3260 | + ctx, &invoicesrpc.CancelInvoiceMsg{ |
| 3261 | + PaymentHash: payHash[:], |
| 3262 | + }, |
| 3263 | + ) |
| 3264 | + require.NoError(t.t, err) |
| 3265 | + |
| 3266 | + assertNumHtlcs(t.t, dave, 0) |
| 3267 | + assertNumHtlcs(t.t, erin, 0) |
| 3268 | + assertNumHtlcs(t.t, yara, 0) |
| 3269 | + |
| 3270 | + logBalance(t.t, nodes, assetID, "after cancelled hodl") |
| 3271 | + |
| 3272 | + // Now let's create a normal invoice that will be settled once all the |
| 3273 | + // HTLCs have been received. This is only possible because the payer |
| 3274 | + // uses multiple bolt11 hop hints to reach the destination. |
| 3275 | + invoiceResp := createAssetInvoice(t.t, nil, fabia, 15_000, assetID) |
| 3276 | + |
| 3277 | + payInvoiceWithSatoshi( |
| 3278 | + t.t, charlie, invoiceResp, withGroupKey(groupID), |
| 3279 | + ) |
| 3280 | + |
| 3281 | + logBalance(t.t, nodes, assetID, "after multi-rfq receive") |
| 3282 | +} |
| 3283 | + |
3129 | 3284 | // testCustomChannelsStrictForwarding is a test that tests the strict forwarding |
3130 | 3285 | // behavior of a node when it comes to paying asset invoices with assets and |
3131 | 3286 | // BTC invoices with satoshis. |
|
0 commit comments