Merge pull request #7415 from bitromortac/2302-max-htlc

routing+discovery: fail non-maxHTLC channel updates in validation
This commit is contained in:
Oliver Gugger authored and GitHub committed 2023-02-22 08:45:56 +01:00
commit b3e27f9ba7
17 files changed
+118 -54

No files matched your search

+17 -2
View File
@@ -7,6 +7,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/netann"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/routing/route"
)
@@ -131,10 +132,24 @@ func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash,
updates = append(updates, chanAnn)
if edge1 != nil {
updates = append(updates, edge1)
// We don't want to send channel updates that don't
// conform to the spec (anymore).
err := routing.ValidateChannelUpdateFields(0, edge1)
if err != nil {
log.Errorf("not sending invalid channel "+
"update %v: %v", edge1, err)
} else {
updates = append(updates, edge1)
}
}
if edge2 != nil {
updates = append(updates, edge2)
err := routing.ValidateChannelUpdateFields(0, edge2)
if err != nil {
log.Errorf("not sending invalid channel "+
"update %v: %v", edge2, err)
} else {
updates = append(updates, edge2)
}
}
}
+1 -1
View File
@@ -1533,7 +1533,7 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error {
if !edge.MessageFlags.HasMaxHtlc() {
// We'll make sure we support the new max_htlc field if
// not already present.
edge.MessageFlags |= lnwire.ChanUpdateOptionMaxHtlc
edge.MessageFlags |= lnwire.ChanUpdateRequiredMaxHtlc
edge.MaxHTLC = lnwire.NewMSatFromSatoshis(info.Capacity)
edgesToUpdate = append(edgesToUpdate, updateTuple{
+55 -13
View File
@@ -582,7 +582,7 @@ func createUpdateAnnouncement(blockHeight uint32,
BlockHeight: blockHeight,
},
Timestamp: timestamp,
MessageFlags: lnwire.ChanUpdateOptionMaxHtlc,
MessageFlags: lnwire.ChanUpdateRequiredMaxHtlc,
ChannelFlags: flags,
TimeLockDelta: uint16(prand.Int63()),
HtlcMinimumMsat: htlcMinMsat,
@@ -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