From 7bbf89625fd98fc912289c99bf9428d31e2fe3d1 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 11 Sep 2024 12:27:14 +0200 Subject: [PATCH] multi: move ChannelUpdate validate methods to netann --- discovery/chan_series.go | 5 +-- discovery/gossiper.go | 6 +-- go.mod | 2 +- graph/ann_validation.go | 70 ---------------------------------- graph/builder.go | 3 +- netann/channel_update.go | 71 +++++++++++++++++++++++++++++++++++ netann/channel_update_test.go | 3 +- routing/payment_session.go | 4 +- 8 files changed, 82 insertions(+), 82 deletions(-) diff --git a/discovery/chan_series.go b/discovery/chan_series.go index ede116683..b7b9af989 100644 --- a/discovery/chan_series.go +++ b/discovery/chan_series.go @@ -5,7 +5,6 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/graph" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing/route" @@ -137,7 +136,7 @@ func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash, if edge1 != nil { // We don't want to send channel updates that don't // conform to the spec (anymore). - err := graph.ValidateChannelUpdateFields(0, edge1) + err := netann.ValidateChannelUpdateFields(0, edge1) if err != nil { log.Errorf("not sending invalid channel "+ "update %v: %v", edge1, err) @@ -146,7 +145,7 @@ func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash, } } if edge2 != nil { - err := graph.ValidateChannelUpdateFields(0, edge2) + err := netann.ValidateChannelUpdateFields(0, edge2) if err != nil { log.Errorf("not sending invalid channel "+ "update %v: %v", edge2, err) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 300a880b0..ee1e2916b 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -2100,7 +2100,7 @@ func (d *AuthenticatedGossiper) processZombieUpdate( "with chan_id=%v", msg.ShortChannelID) } - err := graph.VerifyChannelUpdateSignature(msg, pubKey) + err := netann.VerifyChannelUpdateSignature(msg, pubKey) if err != nil { return fmt.Errorf("unable to verify channel "+ "update signature: %v", err) @@ -2237,7 +2237,7 @@ func (d *AuthenticatedGossiper) updateChannel(info *models.ChannelEdgeInfo, // To ensure that our signature is valid, we'll verify it ourself // before committing it to the slice returned. - err = graph.ValidateChannelUpdateAnn( + err = netann.ValidateChannelUpdateAnn( d.selfKey, info.Capacity, chanUpdate, ) if err != nil { @@ -3028,7 +3028,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg, // Validate the channel announcement with the expected public key and // channel capacity. In the case of an invalid channel update, we'll // return an error to the caller and exit early. - err = graph.ValidateChannelUpdateAnn(pubKey, chanInfo.Capacity, upd) + err = netann.ValidateChannelUpdateAnn(pubKey, chanInfo.Capacity, upd) if err != nil { rErr := fmt.Errorf("unable to validate channel update "+ "announcement for short_chan_id=%v: %v", diff --git a/go.mod b/go.mod index 65a4f991f..4aeea3808 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( github.com/lightningnetwork/lnd/tor v1.1.2 github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 github.com/miekg/dns v1.1.43 + github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.11.1 github.com/stretchr/testify v1.9.0 github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 @@ -135,7 +136,6 @@ require ( github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runc v1.1.12 // indirect github.com/ory/dockertest/v3 v3.10.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect diff --git a/graph/ann_validation.go b/graph/ann_validation.go index 4cbf3737b..3c93d06e5 100644 --- a/graph/ann_validation.go +++ b/graph/ann_validation.go @@ -2,12 +2,9 @@ package graph import ( "bytes" - "fmt" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/lnwire" ) @@ -48,70 +45,3 @@ func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error { return nil } - -// ValidateChannelUpdateAnn validates the channel update announcement by -// checking (1) that the included signature covers the announcement and has been -// signed by the node's private key, and (2) that the announcement's message -// flags and optional fields are sane. -func ValidateChannelUpdateAnn(pubKey *btcec.PublicKey, capacity btcutil.Amount, - a *lnwire.ChannelUpdate1) error { - - if err := ValidateChannelUpdateFields(capacity, a); err != nil { - return err - } - - return VerifyChannelUpdateSignature(a, pubKey) -} - -// VerifyChannelUpdateSignature verifies that the channel update message was -// signed by the party with the given node public key. -func VerifyChannelUpdateSignature(msg *lnwire.ChannelUpdate1, - pubKey *btcec.PublicKey) error { - - data, err := msg.DataToSign() - if err != nil { - return fmt.Errorf("unable to reconstruct message data: %w", err) - } - dataHash := chainhash.DoubleHashB(data) - - nodeSig, err := msg.Signature.ToSignature() - if err != nil { - return err - } - - if !nodeSig.Verify(dataHash, pubKey) { - return fmt.Errorf("invalid signature for channel update %v", - spew.Sdump(msg)) - } - - return nil -} - -// ValidateChannelUpdateFields validates a channel update's message flags and -// corresponding update fields. -func ValidateChannelUpdateFields(capacity btcutil.Amount, - msg *lnwire.ChannelUpdate1) error { - - // The maxHTLC flag is mandatory. - if !msg.MessageFlags.HasMaxHtlc() { - return errors.Errorf("max htlc flag not set for channel "+ - "update %v", spew.Sdump(msg)) - } - - maxHtlc := msg.HtlcMaximumMsat - if maxHtlc == 0 || maxHtlc < msg.HtlcMinimumMsat { - return errors.Errorf("invalid max htlc for channel "+ - "update %v", spew.Sdump(msg)) - } - - // For light clients, the capacity will not be set so we'll skip - // checking whether the MaxHTLC value respects the channel's - // capacity. - capacityMsat := lnwire.NewMSatFromSatoshis(capacity) - if capacityMsat != 0 && maxHtlc > capacityMsat { - return errors.Errorf("max_htlc (%v) for channel update "+ - "greater than capacity (%v)", maxHtlc, capacityMsat) - } - - return nil -} diff --git a/graph/builder.go b/graph/builder.go index d629523f4..8b8b40d64 100644 --- a/graph/builder.go +++ b/graph/builder.go @@ -27,6 +27,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chanvalidate" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/multimutex" + "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing/chainview" "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/ticker" @@ -1484,7 +1485,7 @@ func (b *Builder) ApplyChannelUpdate(msg *lnwire.ChannelUpdate1) bool { return false } - err = ValidateChannelUpdateAnn(pubKey, ch.Capacity, msg) + err = netann.ValidateChannelUpdateAnn(pubKey, ch.Capacity, msg) if err != nil { log.Errorf("Unable to validate channel update: %v", err) return false diff --git a/netann/channel_update.go b/netann/channel_update.go index c8992ccc6..609a26a1e 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -6,10 +6,14 @@ import ( "time" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" + "github.com/pkg/errors" ) // ErrUnableToExtractChanUpdate is returned when a channel update cannot be @@ -152,3 +156,70 @@ func ChannelUpdateFromEdge(info *models.ChannelEdgeInfo, return update, nil } + +// ValidateChannelUpdateAnn validates the channel update announcement by +// checking (1) that the included signature covers the announcement and has been +// signed by the node's private key, and (2) that the announcement's message +// flags and optional fields are sane. +func ValidateChannelUpdateAnn(pubKey *btcec.PublicKey, capacity btcutil.Amount, + a *lnwire.ChannelUpdate1) error { + + if err := ValidateChannelUpdateFields(capacity, a); err != nil { + return err + } + + return VerifyChannelUpdateSignature(a, pubKey) +} + +// VerifyChannelUpdateSignature verifies that the channel update message was +// signed by the party with the given node public key. +func VerifyChannelUpdateSignature(msg *lnwire.ChannelUpdate1, + pubKey *btcec.PublicKey) error { + + data, err := msg.DataToSign() + if err != nil { + return fmt.Errorf("unable to reconstruct message data: %w", err) + } + dataHash := chainhash.DoubleHashB(data) + + nodeSig, err := msg.Signature.ToSignature() + if err != nil { + return err + } + + if !nodeSig.Verify(dataHash, pubKey) { + return fmt.Errorf("invalid signature for channel update %v", + spew.Sdump(msg)) + } + + return nil +} + +// ValidateChannelUpdateFields validates a channel update's message flags and +// corresponding update fields. +func ValidateChannelUpdateFields(capacity btcutil.Amount, + msg *lnwire.ChannelUpdate1) error { + + // The maxHTLC flag is mandatory. + if !msg.MessageFlags.HasMaxHtlc() { + return errors.Errorf("max htlc flag not set for channel "+ + "update %v", spew.Sdump(msg)) + } + + maxHtlc := msg.HtlcMaximumMsat + if maxHtlc == 0 || maxHtlc < msg.HtlcMinimumMsat { + return errors.Errorf("invalid max htlc for channel "+ + "update %v", spew.Sdump(msg)) + } + + // For light clients, the capacity will not be set so we'll skip + // checking whether the MaxHTLC value respects the channel's + // capacity. + capacityMsat := lnwire.NewMSatFromSatoshis(capacity) + if capacityMsat != 0 && maxHtlc > capacityMsat { + return errors.Errorf("max_htlc (%v) for channel update "+ + "greater than capacity (%v)", maxHtlc, capacityMsat) + } + + return nil +} diff --git a/netann/channel_update_test.go b/netann/channel_update_test.go index 2a9ed2e98..2a619e062 100644 --- a/netann/channel_update_test.go +++ b/netann/channel_update_test.go @@ -7,7 +7,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" - "github.com/lightningnetwork/lnd/graph" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" @@ -182,7 +181,7 @@ func TestUpdateDisableFlag(t *testing.T) { // Finally, validate the signature using the router's // verification logic. - err = graph.VerifyChannelUpdateSignature( + err = netann.VerifyChannelUpdateSignature( newUpdate, pubKey, ) if err != nil { diff --git a/routing/payment_session.go b/routing/payment_session.go index e07de73b7..b47f6ee0c 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -8,9 +8,9 @@ import ( "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" - "github.com/lightningnetwork/lnd/graph" "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing/route" ) @@ -440,7 +440,7 @@ func (p *paymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate1, pubKey *btcec.PublicKey, policy *models.CachedEdgePolicy) bool { // Validate the message signature. - if err := graph.VerifyChannelUpdateSignature(msg, pubKey); err != nil { + if err := netann.VerifyChannelUpdateSignature(msg, pubKey); err != nil { log.Errorf( "Unable to validate channel update signature: %v", err, )