routing: stricter maxHTLC checks
We require channel updates to have the max HTLC message flag set. Several flows need to pass that check before channel updates are forwarded to peers: * after channel funding: `addToRouterGraph` * after receiving channel updates from a peer: `ProcessRemoteAnnouncement` * after we update channel policies: `PropagateChanPolicyUpdate`
This commit is contained in:
4 files changed
+77
-29
No files matched your search
+54
-12
@@ -859,9 +859,30 @@ func TestProcessAnnouncement(t *testing.T) {
|
||||
t.Fatalf("edge wasn't added to router: %v", err)
|
||||
}
|
||||
|
||||
// We'll craft an invalid channel update, setting no message flags.
|
||||
ua, err := createUpdateAnnouncement(0, 0, remoteKeyPriv1, timestamp)
|
||||
require.NoError(t, err, "can't create update announcement")
|
||||
ua.MessageFlags = 0
|
||||
|
||||
// We send an invalid channel update and expect it to fail.
|
||||
select {
|
||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(ua, nodePeer):
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("remote announcement not processed")
|
||||
}
|
||||
require.ErrorContains(t, err, "max htlc flag not set for channel "+
|
||||
"update")
|
||||
|
||||
// We should not broadcast the channel update.
|
||||
select {
|
||||
case <-ctx.broadcastedMessage:
|
||||
t.Fatal("gossiper should not have broadcast channel update")
|
||||
case <-time.After(2 * trickleDelay):
|
||||
}
|
||||
|
||||
// We'll then craft the channel policy of the remote party and also send
|
||||
// it to the gossiper.
|
||||
ua, err := createUpdateAnnouncement(0, 0, remoteKeyPriv1, timestamp)
|
||||
ua, err = createUpdateAnnouncement(0, 0, remoteKeyPriv1, timestamp)
|
||||
require.NoError(t, err, "can't create update announcement")
|
||||
|
||||
select {
|
||||
@@ -2861,24 +2882,26 @@ func TestNodeAnnouncementNoChannels(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestOptionalFieldsChannelUpdateValidation tests that we're able to properly
|
||||
// validate the msg flags and optional max HTLC field of a ChannelUpdate.
|
||||
// validate the msg flags and max HTLC field of a ChannelUpdate.
|
||||
func TestOptionalFieldsChannelUpdateValidation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx, err := createTestCtx(t, 0)
|
||||
require.NoError(t, err, "can't create context")
|
||||
|
||||
processRemoteAnnouncement := ctx.gossiper.ProcessRemoteAnnouncement
|
||||
|
||||
chanUpdateHeight := uint32(0)
|
||||
timestamp := uint32(123456)
|
||||
nodePeer := &mockPeer{remoteKeyPriv1.PubKey(), nil, nil}
|
||||
|
||||
// In this scenario, we'll test whether the message flags field in a channel
|
||||
// update is properly handled.
|
||||
// In this scenario, we'll test whether the message flags field in a
|
||||
// channel update is properly handled.
|
||||
chanAnn, err := createRemoteChannelAnnouncement(chanUpdateHeight)
|
||||
require.NoError(t, err, "can't create channel announcement")
|
||||
|
||||
select {
|
||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(chanAnn, nodePeer):
|
||||
case err = <-processRemoteAnnouncement(chanAnn, nodePeer):
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not process remote announcement")
|
||||
}
|
||||
@@ -2886,7 +2909,9 @@ func TestOptionalFieldsChannelUpdateValidation(t *testing.T) {
|
||||
|
||||
// The first update should fail from an invalid max HTLC field, which is
|
||||
// less than the min HTLC.
|
||||
chanUpdAnn, err := createUpdateAnnouncement(0, 0, remoteKeyPriv1, timestamp)
|
||||
chanUpdAnn, err := createUpdateAnnouncement(
|
||||
0, 0, remoteKeyPriv1, timestamp,
|
||||
)
|
||||
require.NoError(t, err, "unable to create channel update")
|
||||
|
||||
chanUpdAnn.HtlcMinimumMsat = 5000
|
||||
@@ -2896,7 +2921,7 @@ func TestOptionalFieldsChannelUpdateValidation(t *testing.T) {
|
||||
}
|
||||
|
||||
select {
|
||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case err = <-processRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not process remote announcement")
|
||||
}
|
||||
@@ -2913,7 +2938,7 @@ func TestOptionalFieldsChannelUpdateValidation(t *testing.T) {
|
||||
}
|
||||
|
||||
select {
|
||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case err = <-processRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not process remote announcement")
|
||||
}
|
||||
@@ -2921,19 +2946,36 @@ func TestOptionalFieldsChannelUpdateValidation(t *testing.T) {
|
||||
t.Fatalf("expected chan update to error, instead got %v", err)
|
||||
}
|
||||
|
||||
// The final update should succeed, since setting the flag 0 means the
|
||||
// nonsense max_htlc field will just be ignored.
|
||||
// The third update should not succeed, a channel update with no message
|
||||
// flag set is invalid.
|
||||
chanUpdAnn.MessageFlags = 0
|
||||
if err := signUpdate(remoteKeyPriv1, chanUpdAnn); err != nil {
|
||||
t.Fatalf("unable to sign channel update: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case err = <-processRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not process remote announcement")
|
||||
}
|
||||
require.NoError(t, err, "unable to process announcement")
|
||||
require.ErrorContains(t, err, "max htlc flag not set")
|
||||
|
||||
// The final update should succeed.
|
||||
chanUpdAnn, err = createUpdateAnnouncement(
|
||||
0, 0, remoteKeyPriv1, timestamp,
|
||||
)
|
||||
require.NoError(t, err, "unable to create channel update")
|
||||
|
||||
if err := signUpdate(remoteKeyPriv1, chanUpdAnn); err != nil {
|
||||
t.Fatalf("unable to sign channel update: %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case err = <-processRemoteAnnouncement(chanUpdAnn, nodePeer):
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("did not process remote announcement")
|
||||
}
|
||||
require.NoError(t, err, "expected update to be processed")
|
||||
}
|
||||
|
||||
// TestSendChannelUpdateReliably ensures that the latest channel update for a
|
||||
|
||||
Reference in new issue
Block a user