mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-10-11 05:42:48 +02:00
In this commit, we enhance the itess to exercise the new query+reset+import namespace features. This also rounds out the test as well to make sure that the mc payment portion works properly.
201 lines
6.0 KiB
Go
201 lines
6.0 KiB
Go
package itest
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
|
"github.com/lightningnetwork/lnd/lnrpc"
|
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
|
"github.com/lightningnetwork/lnd/lntest"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// testMissionControlNamespace tests that payments can use different mission
|
|
// control namespaces to maintain separate routing histories.
|
|
func testMissionControlNamespace(ht *lntest.HarnessTest) {
|
|
const chanAmt = btcutil.Amount(1_000_000)
|
|
|
|
// We'll create a simple two node network for this tesat.
|
|
alice := ht.NewNodeWithCoins("Alice", nil)
|
|
bob := ht.NewNode("Bob", nil)
|
|
ht.EnsureConnected(alice, bob)
|
|
chanPoint := ht.OpenChannel(
|
|
alice, bob, lntest.OpenChannelParams{
|
|
Amt: chanAmt,
|
|
},
|
|
)
|
|
|
|
ht.AssertChannelInGraph(alice, chanPoint)
|
|
ht.AssertChannelInGraph(bob, chanPoint)
|
|
|
|
// Create an invoice for Bob that we'll pay below.
|
|
const paymentAmt = 10_000
|
|
invoice := bob.RPC.AddInvoice(&lnrpc.Invoice{
|
|
Value: paymentAmt,
|
|
Memo: "test payment default namespace",
|
|
})
|
|
|
|
// Reset mission control for the default namespace to ensure clean
|
|
// state.
|
|
_, err := alice.RPC.Router.ResetMissionControl(
|
|
ht.Context(), &routerrpc.ResetMissionControlRequest{
|
|
MissionControlNamespace: "",
|
|
},
|
|
)
|
|
require.NoError(ht.T, err, "failed to reset default mission control")
|
|
|
|
ht.Run("send_payment_with_namespaces", func(t *testing.T) {
|
|
// Send a payment using the default namespace.
|
|
reqDefault := &routerrpc.SendPaymentRequest{
|
|
PaymentRequest: invoice.PaymentRequest,
|
|
TimeoutSeconds: 60,
|
|
MissionControlNamespace: "",
|
|
}
|
|
ht.SendPaymentAssertSettled(alice, reqDefault)
|
|
|
|
// Make another payment with Bob but use our custom namespace
|
|
// this time instead.
|
|
invoice2 := bob.RPC.AddInvoice(&lnrpc.Invoice{
|
|
Value: paymentAmt,
|
|
Memo: "test payment custom namespace",
|
|
})
|
|
customNs := "custom-namespace-send"
|
|
reqCustom := &routerrpc.SendPaymentRequest{
|
|
PaymentRequest: invoice2.PaymentRequest,
|
|
TimeoutSeconds: 60,
|
|
MissionControlNamespace: customNs,
|
|
}
|
|
payment := ht.SendPaymentAssertSettled(alice, reqCustom)
|
|
require.Equal(t, lnrpc.Payment_SUCCEEDED, payment.Status,
|
|
"payment with custom namespace should succeed")
|
|
|
|
// If we query for the default mc, then we should find that the
|
|
// records are populated.
|
|
mcReqDefault := &routerrpc.QueryMissionControlRequest{
|
|
MissionControlNamespace: "",
|
|
}
|
|
defaultMC, err := alice.RPC.Router.QueryMissionControl(
|
|
ht.Context(), mcReqDefault,
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, defaultMC.Pairs,
|
|
"default namespace should have recorded channel usage")
|
|
|
|
// Similarly, we should find that the custom namespace also has
|
|
// entries.
|
|
mcReqCustom := &routerrpc.QueryMissionControlRequest{
|
|
MissionControlNamespace: customNs,
|
|
}
|
|
customMC, err := alice.RPC.Router.QueryMissionControl(
|
|
ht.Context(), mcReqCustom,
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, customMC.Pairs,
|
|
"custom namespace should have recorded channel usage")
|
|
|
|
require.True(t, len(defaultMC.Pairs) > 0, "Default MC empty")
|
|
require.True(t, len(customMC.Pairs) > 0, "Custom MC empty")
|
|
})
|
|
|
|
ht.Run("reset_mission_control_with_namespace", func(t *testing.T) {
|
|
customNsReset := "namespace-to-reset"
|
|
|
|
// Send a payment to populate this new custom namespace.
|
|
invReset := bob.RPC.AddInvoice(&lnrpc.Invoice{Value: 100})
|
|
reqPopulate := &routerrpc.SendPaymentRequest{
|
|
PaymentRequest: invReset.PaymentRequest,
|
|
TimeoutSeconds: 60,
|
|
MissionControlNamespace: customNsReset,
|
|
}
|
|
ht.SendPaymentAssertSettled(alice, reqPopulate)
|
|
|
|
// Query the namespace, we should find now that it has some
|
|
// entries populated.
|
|
mcBeforeReset, err := alice.RPC.Router.QueryMissionControl(
|
|
ht.Context(), &routerrpc.QueryMissionControlRequest{
|
|
MissionControlNamespace: customNsReset,
|
|
},
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(
|
|
t, mcBeforeReset.Pairs, "MC should be populated "+
|
|
"before reset",
|
|
)
|
|
|
|
// Now, we'll reset the ns, then check below that it's actually
|
|
// empty.
|
|
_, errReset := alice.RPC.Router.ResetMissionControl(
|
|
ht.Context(), &routerrpc.ResetMissionControlRequest{
|
|
MissionControlNamespace: customNsReset,
|
|
},
|
|
)
|
|
require.NoError(t, errReset)
|
|
|
|
// Query again to confirm it's empty.
|
|
mcAfterReset, err := alice.RPC.Router.QueryMissionControl(
|
|
ht.Context(), &routerrpc.QueryMissionControlRequest{
|
|
MissionControlNamespace: customNsReset,
|
|
},
|
|
)
|
|
require.NoError(t, err)
|
|
require.Empty(
|
|
t, mcAfterReset.Pairs, "MC should be empty after reset",
|
|
)
|
|
|
|
// Now we'll test isolation: the default namespace shouldn't
|
|
// have been affected.
|
|
defaultMC, err := alice.RPC.Router.QueryMissionControl(
|
|
ht.Context(), &routerrpc.QueryMissionControlRequest{
|
|
MissionControlNamespace: "",
|
|
},
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(
|
|
t, defaultMC.Pairs, "Default MC should not be empty",
|
|
)
|
|
})
|
|
|
|
ht.Run("ximport_mission_control_with_namespace", func(t *testing.T) {
|
|
customNs := "namespace-to-import"
|
|
|
|
// We'll make some fake data to import as weights.
|
|
importData := &routerrpc.XImportMissionControlRequest{ //nolint:ll
|
|
MissionControlNamespace: customNs,
|
|
Pairs: []*routerrpc.PairHistory{
|
|
{
|
|
NodeFrom: alice.PubKey[:],
|
|
NodeTo: bob.PubKey[:],
|
|
History: &routerrpc.PairData{
|
|
FailTime: time.Now().Unix() - 1000,
|
|
FailAmtMsat: 5000,
|
|
SuccessTime: time.Now().Unix(),
|
|
SuccessAmtMsat: 10000,
|
|
},
|
|
},
|
|
},
|
|
Force: true,
|
|
}
|
|
|
|
_, err := alice.RPC.Router.XImportMissionControl(
|
|
ht.Context(), importData,
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// That data that we created above should be found now.
|
|
mcAfterImport, err := alice.RPC.Router.QueryMissionControl(
|
|
ht.Context(), &routerrpc.QueryMissionControlRequest{
|
|
MissionControlNamespace: customNs,
|
|
},
|
|
)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(
|
|
t, mcAfterImport.Pairs, "MC should have imported data",
|
|
)
|
|
require.Equal(
|
|
t, int64(10000),
|
|
mcAfterImport.Pairs[0].History.SuccessAmtMsat,
|
|
)
|
|
})
|
|
}
|