|
|
|
@ -3,7 +3,6 @@ package itest
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"math"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
|
|
|
@ -11,6 +10,9 @@ import (
|
|
|
|
|
"github.com/lightningnetwork/lnd/chainreg"
|
|
|
|
|
"github.com/lightningnetwork/lnd/funding"
|
|
|
|
|
"github.com/lightningnetwork/lnd/lnrpc"
|
|
|
|
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
|
|
|
|
"github.com/lightningnetwork/lnd/lntemp"
|
|
|
|
|
"github.com/lightningnetwork/lnd/lntemp/node"
|
|
|
|
|
"github.com/lightningnetwork/lnd/lntest"
|
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
@ -18,6 +20,7 @@ import (
|
|
|
|
|
|
|
|
|
|
// assertPolicyUpdate checks that a given policy update has been received by a
|
|
|
|
|
// list of given nodes.
|
|
|
|
|
// TODO(yy): delete.
|
|
|
|
|
func assertPolicyUpdate(t *harnessTest, nodes []*lntest.HarnessNode,
|
|
|
|
|
advertisingNode string, policy *lnrpc.RoutingPolicy,
|
|
|
|
|
chanPoint *lnrpc.ChannelPoint) {
|
|
|
|
@ -30,10 +33,8 @@ func assertPolicyUpdate(t *harnessTest, nodes []*lntest.HarnessNode,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// testUpdateChannelPolicy tests that policy updates made to a channel
|
|
|
|
|
// get propagated to other nodes in the network.
|
|
|
|
|
func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
ctxb := context.Background()
|
|
|
|
|
|
|
|
|
|
// gets propagated to other nodes in the network.
|
|
|
|
|
func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|
|
|
|
const (
|
|
|
|
|
defaultFeeBase = 1000
|
|
|
|
|
defaultFeeRate = 1
|
|
|
|
@ -45,19 +46,19 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
chanAmt := funding.MaxBtcFundingAmount
|
|
|
|
|
pushAmt := chanAmt / 2
|
|
|
|
|
|
|
|
|
|
alice, bob := ht.Alice, ht.Bob
|
|
|
|
|
|
|
|
|
|
// Create a channel Alice->Bob.
|
|
|
|
|
chanPoint := openChannelAndAssert(
|
|
|
|
|
t, net, net.Alice, net.Bob,
|
|
|
|
|
lntest.OpenChannelParams{
|
|
|
|
|
chanPoint := ht.OpenChannel(
|
|
|
|
|
alice, bob, lntemp.OpenChannelParams{
|
|
|
|
|
Amt: chanAmt,
|
|
|
|
|
PushAmt: pushAmt,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
defer closeChannelAndAssert(t, net, net.Alice, chanPoint, false)
|
|
|
|
|
|
|
|
|
|
// We add all the nodes' update channels to a slice, such that we can
|
|
|
|
|
// make sure they all receive the expected updates.
|
|
|
|
|
nodes := []*lntest.HarnessNode{net.Alice, net.Bob}
|
|
|
|
|
nodes := []*node.HarnessNode{alice, bob}
|
|
|
|
|
|
|
|
|
|
// Alice and Bob should see each other's ChannelUpdates, advertising the
|
|
|
|
|
// default routing policies.
|
|
|
|
@ -69,65 +70,45 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
MaxHtlcMsat: defaultMaxHtlc,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, net.Alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, net.Bob.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertNodesPolicyUpdate(ht, nodes, alice, expectedPolicy, chanPoint)
|
|
|
|
|
assertNodesPolicyUpdate(ht, nodes, bob, expectedPolicy, chanPoint)
|
|
|
|
|
|
|
|
|
|
// They should now know about the default policies.
|
|
|
|
|
for _, node := range nodes {
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, node, net.Alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, node, net.Bob.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, bob.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := net.Alice.WaitForNetworkChannelOpen(chanPoint)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("alice didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
err = net.Bob.WaitForNetworkChannelOpen(chanPoint)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("bob didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create Carol with options to rate limit channel updates up to 2 per
|
|
|
|
|
// day, and create a new channel Bob->Carol.
|
|
|
|
|
carol := net.NewNode(
|
|
|
|
|
t.t, "Carol", []string{
|
|
|
|
|
carol := ht.NewNode(
|
|
|
|
|
"Carol", []string{
|
|
|
|
|
"--gossip.max-channel-update-burst=2",
|
|
|
|
|
"--gossip.channel-update-interval=24h",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Clean up carol's node when the test finishes.
|
|
|
|
|
defer shutdownAndAssert(net, t, carol)
|
|
|
|
|
|
|
|
|
|
ht.ConnectNodes(carol, bob)
|
|
|
|
|
nodes = append(nodes, carol)
|
|
|
|
|
|
|
|
|
|
// Send some coins to Carol that can be used for channel funding.
|
|
|
|
|
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, carol)
|
|
|
|
|
|
|
|
|
|
net.ConnectNodes(t.t, carol, net.Bob)
|
|
|
|
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
|
|
|
|
|
|
|
|
|
// Open the channel Carol->Bob with a custom min_htlc value set. Since
|
|
|
|
|
// Carol is opening the channel, she will require Bob to not forward
|
|
|
|
|
// HTLCs smaller than this value, and hence he should advertise it as
|
|
|
|
|
// part of his ChannelUpdate.
|
|
|
|
|
const customMinHtlc = 5000
|
|
|
|
|
chanPoint2 := openChannelAndAssert(
|
|
|
|
|
t, net, carol, net.Bob,
|
|
|
|
|
lntest.OpenChannelParams{
|
|
|
|
|
chanPoint2 := ht.OpenChannel(
|
|
|
|
|
carol, bob, lntemp.OpenChannelParams{
|
|
|
|
|
Amt: chanAmt,
|
|
|
|
|
PushAmt: pushAmt,
|
|
|
|
|
MinHtlc: customMinHtlc,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
defer closeChannelAndAssert(t, net, net.Bob, chanPoint2, false)
|
|
|
|
|
|
|
|
|
|
expectedPolicyBob := &lnrpc.RoutingPolicy{
|
|
|
|
|
FeeBaseMsat: defaultFeeBase,
|
|
|
|
@ -144,37 +125,24 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
MaxHtlcMsat: defaultMaxHtlc,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, net.Bob.PubKeyStr, expectedPolicyBob, chanPoint2,
|
|
|
|
|
)
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, carol.PubKeyStr, expectedPolicyCarol, chanPoint2,
|
|
|
|
|
assertNodesPolicyUpdate(ht, nodes, bob, expectedPolicyBob, chanPoint2)
|
|
|
|
|
assertNodesPolicyUpdate(
|
|
|
|
|
ht, nodes, carol, expectedPolicyCarol, chanPoint2,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Check that all nodes now know about the updated policies.
|
|
|
|
|
for _, node := range nodes {
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, node, net.Bob.PubKeyStr, expectedPolicyBob,
|
|
|
|
|
chanPoint2,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, bob.PubKeyStr, expectedPolicyBob, chanPoint2,
|
|
|
|
|
)
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, node, carol.PubKeyStr, expectedPolicyCarol,
|
|
|
|
|
chanPoint2,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, carol.PubKeyStr, expectedPolicyCarol, chanPoint2,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = net.Alice.WaitForNetworkChannelOpen(chanPoint2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("alice didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
err = net.Bob.WaitForNetworkChannelOpen(chanPoint2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("bob didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
err = carol.WaitForNetworkChannelOpen(chanPoint2)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("carol didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
// Make sure Alice and Carol have seen each other's channels.
|
|
|
|
|
ht.AssertTopologyChannelOpen(alice, chanPoint2)
|
|
|
|
|
ht.AssertTopologyChannelOpen(carol, chanPoint)
|
|
|
|
|
|
|
|
|
|
// First we'll try to send a payment from Alice to Carol with an amount
|
|
|
|
|
// less than the min_htlc value required by Carol. This payment should
|
|
|
|
@ -184,23 +152,19 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
Memo: "testing",
|
|
|
|
|
Value: int64(payAmt),
|
|
|
|
|
}
|
|
|
|
|
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
resp, err := carol.AddInvoice(ctxt, invoice)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to add invoice: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = completePaymentRequests(
|
|
|
|
|
net.Alice, net.Alice.RouterClient,
|
|
|
|
|
[]string{resp.PaymentRequest}, true,
|
|
|
|
|
)
|
|
|
|
|
resp := carol.RPC.AddInvoice(invoice)
|
|
|
|
|
|
|
|
|
|
// Alice knows about the channel policy of Carol and should therefore
|
|
|
|
|
// not be able to find a path during routing.
|
|
|
|
|
expErr := lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE
|
|
|
|
|
if err.Error() != expErr.String() {
|
|
|
|
|
t.Fatalf("expected %v, instead got %v", expErr, err)
|
|
|
|
|
payReq := &routerrpc.SendPaymentRequest{
|
|
|
|
|
PaymentRequest: resp.PaymentRequest,
|
|
|
|
|
TimeoutSeconds: 60,
|
|
|
|
|
FeeLimitMsat: noFeeLimitMsat,
|
|
|
|
|
}
|
|
|
|
|
ht.SendPaymentAssertFail(
|
|
|
|
|
alice, payReq,
|
|
|
|
|
lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Now we try to send a payment over the channel with a value too low
|
|
|
|
|
// to be accepted. First we query for a route to route a payment of
|
|
|
|
@ -211,16 +175,8 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
Amt: int64(payAmt),
|
|
|
|
|
FinalCltvDelta: defaultTimeLockDelta,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
routes, err := net.Alice.QueryRoutes(ctxt, routesReq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to get route: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(routes.Routes) != 1 {
|
|
|
|
|
t.Fatalf("expected to find 1 route, got %v", len(routes.Routes))
|
|
|
|
|
}
|
|
|
|
|
routes := alice.RPC.QueryRoutes(routesReq)
|
|
|
|
|
require.Len(ht, routes.Routes, 1)
|
|
|
|
|
|
|
|
|
|
// We change the route to carry a payment of 4000 mSAT instead of 5000
|
|
|
|
|
// mSAT.
|
|
|
|
@ -233,27 +189,19 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
|
|
|
|
|
|
|
|
|
|
// Send the payment with the modified value.
|
|
|
|
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
alicePayStream, err := net.Alice.SendToRoute(ctxt) // nolint:staticcheck
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to create payment stream for alice: %v", err)
|
|
|
|
|
}
|
|
|
|
|
alicePayStream := alice.RPC.SendToRoute()
|
|
|
|
|
|
|
|
|
|
sendReq := &lnrpc.SendToRouteRequest{
|
|
|
|
|
PaymentHash: resp.RHash,
|
|
|
|
|
Route: routes.Routes[0],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = alicePayStream.Send(sendReq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
|
}
|
|
|
|
|
err := alicePayStream.Send(sendReq)
|
|
|
|
|
require.NoError(ht, err, "unable to send payment")
|
|
|
|
|
|
|
|
|
|
// We expect this payment to fail, and that the min_htlc value is
|
|
|
|
|
// communicated back to us, since the attempted HTLC value was too low.
|
|
|
|
|
sendResp, err := alicePayStream.Recv()
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
|
}
|
|
|
|
|
require.NoError(ht, err, "unable to receive payment stream")
|
|
|
|
|
|
|
|
|
|
// Expected as part of the error message.
|
|
|
|
|
substrs := []string{
|
|
|
|
@ -261,10 +209,7 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
"HtlcMinimumMsat: (lnwire.MilliSatoshi) 5000 mSAT",
|
|
|
|
|
}
|
|
|
|
|
for _, s := range substrs {
|
|
|
|
|
if !strings.Contains(sendResp.PaymentError, s) {
|
|
|
|
|
t.Fatalf("expected error to contain \"%v\", instead "+
|
|
|
|
|
"got %v", s, sendResp.PaymentError)
|
|
|
|
|
}
|
|
|
|
|
require.Contains(ht, sendResp.PaymentError, s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure sending using the original value succeeds.
|
|
|
|
@ -292,22 +237,14 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = alicePayStream.Send(sendReq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
|
}
|
|
|
|
|
require.NoError(ht, err, "unable to send payment")
|
|
|
|
|
|
|
|
|
|
sendResp, err = alicePayStream.Recv()
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
|
}
|
|
|
|
|
require.NoError(ht, err, "unable to receive payment stream")
|
|
|
|
|
require.Empty(ht, sendResp.PaymentError, "expected payment to succeed")
|
|
|
|
|
|
|
|
|
|
if sendResp.PaymentError != "" {
|
|
|
|
|
t.Fatalf("expected payment to succeed, instead got %v",
|
|
|
|
|
sendResp.PaymentError)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// With our little cluster set up, we'll update the fees and the max htlc
|
|
|
|
|
// size for the Bob side of the Alice->Bob channel, and make sure
|
|
|
|
|
// With our little cluster set up, we'll update the fees and the max
|
|
|
|
|
// htlc size for the Bob side of the Alice->Bob channel, and make sure
|
|
|
|
|
// all nodes learn about it.
|
|
|
|
|
baseFee := int64(1500)
|
|
|
|
|
feeRate := int64(12)
|
|
|
|
@ -331,21 +268,15 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
ChanPoint: chanPoint,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
if _, err := net.Bob.UpdateChannelPolicy(ctxt, req); err != nil {
|
|
|
|
|
t.Fatalf("unable to get alice's balance: %v", err)
|
|
|
|
|
}
|
|
|
|
|
bob.RPC.UpdateChannelPolicy(req)
|
|
|
|
|
|
|
|
|
|
// Wait for all nodes to have seen the policy update done by Bob.
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, net.Bob.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertNodesPolicyUpdate(ht, nodes, bob, expectedPolicy, chanPoint)
|
|
|
|
|
|
|
|
|
|
// Check that all nodes now know about Bob's updated policy.
|
|
|
|
|
for _, node := range nodes {
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, node, net.Bob.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, bob.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -361,39 +292,21 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
Memo: "testing",
|
|
|
|
|
Value: int64(payAmt),
|
|
|
|
|
}
|
|
|
|
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
resp, err = carol.AddInvoice(ctxt, invoice)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to add invoice: %v", err)
|
|
|
|
|
}
|
|
|
|
|
resp = carol.RPC.AddInvoice(invoice)
|
|
|
|
|
|
|
|
|
|
err = completePaymentRequests(
|
|
|
|
|
net.Alice, net.Alice.RouterClient,
|
|
|
|
|
[]string{resp.PaymentRequest}, true,
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
|
}
|
|
|
|
|
ht.CompletePaymentRequests(alice, []string{resp.PaymentRequest})
|
|
|
|
|
|
|
|
|
|
// We'll now open a channel from Alice directly to Carol.
|
|
|
|
|
net.ConnectNodes(t.t, net.Alice, carol)
|
|
|
|
|
chanPoint3 := openChannelAndAssert(
|
|
|
|
|
t, net, net.Alice, carol,
|
|
|
|
|
lntest.OpenChannelParams{
|
|
|
|
|
ht.ConnectNodes(alice, carol)
|
|
|
|
|
chanPoint3 := ht.OpenChannel(
|
|
|
|
|
alice, carol, lntemp.OpenChannelParams{
|
|
|
|
|
Amt: chanAmt,
|
|
|
|
|
PushAmt: pushAmt,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
defer closeChannelAndAssert(t, net, net.Alice, chanPoint3, false)
|
|
|
|
|
|
|
|
|
|
err = net.Alice.WaitForNetworkChannelOpen(chanPoint3)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("alice didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
err = carol.WaitForNetworkChannelOpen(chanPoint3)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("bob didn't report channel: %v", err)
|
|
|
|
|
}
|
|
|
|
|
// Make sure Bob knows this channel.
|
|
|
|
|
ht.AssertTopologyChannelOpen(bob, chanPoint3)
|
|
|
|
|
|
|
|
|
|
// Make a global update, and check that both channels' new policies get
|
|
|
|
|
// propagated.
|
|
|
|
@ -414,28 +327,21 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
MaxHtlcMsat: maxHtlc,
|
|
|
|
|
}
|
|
|
|
|
req.Scope = &lnrpc.PolicyUpdateRequest_Global{}
|
|
|
|
|
|
|
|
|
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
_, err = net.Alice.UpdateChannelPolicy(ctxt, req)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("unable to update alice's channel policy: %v", err)
|
|
|
|
|
}
|
|
|
|
|
alice.RPC.UpdateChannelPolicy(req)
|
|
|
|
|
|
|
|
|
|
// Wait for all nodes to have seen the policy updates for both of
|
|
|
|
|
// Alice's channels.
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, net.Alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, nodes, net.Alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
assertNodesPolicyUpdate(ht, nodes, alice, expectedPolicy, chanPoint)
|
|
|
|
|
assertNodesPolicyUpdate(ht, nodes, alice, expectedPolicy, chanPoint3)
|
|
|
|
|
|
|
|
|
|
// And finally check that all nodes remembers the policy update they
|
|
|
|
|
// received.
|
|
|
|
|
for _, node := range nodes {
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, node, net.Alice.PubKeyStr, expectedPolicy,
|
|
|
|
|
chanPoint, chanPoint3,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
node, alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -443,60 +349,87 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
|
|
|
|
|
// we'll send two more update from Alice. Carol should accept the first,
|
|
|
|
|
// but not the second, as she only allows two updates per day and a day
|
|
|
|
|
// has yet to elapse from the previous update.
|
|
|
|
|
const numUpdatesTilRateLimit = 2
|
|
|
|
|
for i := 0; i < numUpdatesTilRateLimit; i++ {
|
|
|
|
|
prevAlicePolicy := *expectedPolicy
|
|
|
|
|
baseFee *= 2
|
|
|
|
|
expectedPolicy.FeeBaseMsat = baseFee
|
|
|
|
|
req.BaseFeeMsat = baseFee
|
|
|
|
|
|
|
|
|
|
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
|
|
|
|
defer cancel()
|
|
|
|
|
_, err = net.Alice.UpdateChannelPolicy(ctxt, req)
|
|
|
|
|
require.NoError(t.t, err)
|
|
|
|
|
// assertAliceAndBob is a helper closure which updates Alice's policy
|
|
|
|
|
// and asserts that both Alice and Bob have heard and updated the
|
|
|
|
|
// policy in their graph.
|
|
|
|
|
assertAliceAndBob := func(req *lnrpc.PolicyUpdateRequest,
|
|
|
|
|
expectedPolicy *lnrpc.RoutingPolicy) {
|
|
|
|
|
|
|
|
|
|
alice.RPC.UpdateChannelPolicy(req)
|
|
|
|
|
|
|
|
|
|
// Wait for all nodes to have seen the policy updates for both
|
|
|
|
|
// of Alice's channels. Carol will not see the last update as
|
|
|
|
|
// the limit has been reached.
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, []*lntest.HarnessNode{net.Alice, net.Bob},
|
|
|
|
|
net.Alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
assertNodesPolicyUpdate(
|
|
|
|
|
ht, []*node.HarnessNode{alice, bob},
|
|
|
|
|
alice, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, []*lntest.HarnessNode{net.Alice, net.Bob},
|
|
|
|
|
net.Alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
assertNodesPolicyUpdate(
|
|
|
|
|
ht, []*node.HarnessNode{alice, bob},
|
|
|
|
|
alice, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Check that all nodes remember the policy update
|
|
|
|
|
// they received.
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, net.Alice, net.Alice.PubKeyStr,
|
|
|
|
|
expectedPolicy, chanPoint, chanPoint3,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
alice, alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, net.Bob, net.Alice.PubKeyStr,
|
|
|
|
|
expectedPolicy, chanPoint, chanPoint3,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
alice, alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Carol was added last, which is why we check the last index.
|
|
|
|
|
// Since Carol didn't receive the last update, she still has
|
|
|
|
|
// Alice's old policy.
|
|
|
|
|
if i == numUpdatesTilRateLimit-1 {
|
|
|
|
|
expectedPolicy = &prevAlicePolicy
|
|
|
|
|
}
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, []*lntest.HarnessNode{carol},
|
|
|
|
|
net.Alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
bob, alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertPolicyUpdate(
|
|
|
|
|
t, []*lntest.HarnessNode{carol},
|
|
|
|
|
net.Alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
assertChannelPolicy(
|
|
|
|
|
t, carol, net.Alice.PubKeyStr,
|
|
|
|
|
expectedPolicy, chanPoint, chanPoint3,
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
bob, alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Double the base fee and attach to the policy.
|
|
|
|
|
baseFee1 := baseFee * 2
|
|
|
|
|
expectedPolicy.FeeBaseMsat = baseFee1
|
|
|
|
|
req.BaseFeeMsat = baseFee1
|
|
|
|
|
assertAliceAndBob(req, expectedPolicy)
|
|
|
|
|
|
|
|
|
|
// Check that Carol has both heard the policy and updated it in her
|
|
|
|
|
// graph.
|
|
|
|
|
assertNodesPolicyUpdate(
|
|
|
|
|
ht, []*node.HarnessNode{carol},
|
|
|
|
|
alice, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
assertNodesPolicyUpdate(
|
|
|
|
|
ht, []*node.HarnessNode{carol},
|
|
|
|
|
alice, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
carol, alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
carol, alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Double the base fee and attach to the policy.
|
|
|
|
|
baseFee2 := baseFee1 * 2
|
|
|
|
|
expectedPolicy.FeeBaseMsat = baseFee2
|
|
|
|
|
req.BaseFeeMsat = baseFee2
|
|
|
|
|
assertAliceAndBob(req, expectedPolicy)
|
|
|
|
|
|
|
|
|
|
// Since Carol didn't receive the last update, she still has Alice's
|
|
|
|
|
// old policy. We validate this by checking the base fee is the older
|
|
|
|
|
// one.
|
|
|
|
|
expectedPolicy.FeeBaseMsat = baseFee1
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
carol, alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
ht.AssertChannelPolicy(
|
|
|
|
|
carol, alice.PubKeyStr, expectedPolicy, chanPoint3,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Close all channels.
|
|
|
|
|
ht.CloseChannel(alice, chanPoint)
|
|
|
|
|
ht.CloseChannel(bob, chanPoint2)
|
|
|
|
|
ht.CloseChannel(alice, chanPoint3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// testSendUpdateDisableChannel ensures that a channel update with the disable
|
|
|
|
@ -915,3 +848,16 @@ func testUpdateChannelPolicyFeeRateAccuracy(net *lntest.NetworkHarness,
|
|
|
|
|
t, nodes, net.Alice.PubKeyStr, expectedPolicy, chanPoint,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// assertNodesPolicyUpdate checks that a given policy update has been received
|
|
|
|
|
// by a list of given nodes.
|
|
|
|
|
func assertNodesPolicyUpdate(ht *lntemp.HarnessTest, nodes []*node.HarnessNode,
|
|
|
|
|
advertisingNode *node.HarnessNode, policy *lnrpc.RoutingPolicy,
|
|
|
|
|
chanPoint *lnrpc.ChannelPoint) {
|
|
|
|
|
|
|
|
|
|
for _, node := range nodes {
|
|
|
|
|
ht.AssertChannelPolicyUpdate(
|
|
|
|
|
node, advertisingNode, policy, chanPoint, false,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|