From 615db1fc2e698c564ece603bfcf6fb610a1d2be2 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 11 Sep 2024 12:15:44 +0200 Subject: [PATCH] multi: move channel announcement validation to netann from the graph package. --- discovery/gossiper.go | 6 +-- graph/ann_validation.go | 73 --------------------------------- netann/channel_announcement.go | 75 ++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 76 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index a2a215d0d..300a880b0 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -1890,7 +1890,7 @@ func (d *AuthenticatedGossiper) processRejectedEdge( if err != nil { return nil, err } - err = graph.ValidateChannelAnn(chanAnn) + err = netann.ValidateChannelAnn(chanAnn) if err != nil { err := fmt.Errorf("assembled channel announcement proof "+ "for shortChanID=%v isn't valid: %v", @@ -2540,7 +2540,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, // the signatures within the proof as it should be well formed. var proof *models.ChannelAuthProof if nMsg.isRemote { - if err := graph.ValidateChannelAnn(ann); err != nil { + if err := netann.ValidateChannelAnn(ann); err != nil { err := fmt.Errorf("unable to validate announcement: "+ "%v", err) @@ -3434,7 +3434,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg, // With all the necessary components assembled validate the full // channel announcement proof. - if err := graph.ValidateChannelAnn(chanAnn); err != nil { + if err := netann.ValidateChannelAnn(chanAnn); err != nil { err := fmt.Errorf("channel announcement proof for "+ "short_chan_id=%v isn't valid: %v", shortChanID, err) diff --git a/graph/ann_validation.go b/graph/ann_validation.go index d586ff3ae..4cbf3737b 100644 --- a/graph/ann_validation.go +++ b/graph/ann_validation.go @@ -12,79 +12,6 @@ import ( "github.com/lightningnetwork/lnd/lnwire" ) -// ValidateChannelAnn validates the channel announcement message and checks -// that node signatures covers the announcement message, and that the bitcoin -// signatures covers the node keys. -func ValidateChannelAnn(a *lnwire.ChannelAnnouncement1) error { - // First, we'll compute the digest (h) which is to be signed by each of - // the keys included within the node announcement message. This hash - // digest includes all the keys, so the (up to 4 signatures) will - // attest to the validity of each of the keys. - data, err := a.DataToSign() - if err != nil { - return err - } - dataHash := chainhash.DoubleHashB(data) - - // First we'll verify that the passed bitcoin key signature is indeed a - // signature over the computed hash digest. - bitcoinSig1, err := a.BitcoinSig1.ToSignature() - if err != nil { - return err - } - bitcoinKey1, err := btcec.ParsePubKey(a.BitcoinKey1[:]) - if err != nil { - return err - } - if !bitcoinSig1.Verify(dataHash, bitcoinKey1) { - return errors.New("can't verify first bitcoin signature") - } - - // If that checks out, then we'll verify that the second bitcoin - // signature is a valid signature of the bitcoin public key over hash - // digest as well. - bitcoinSig2, err := a.BitcoinSig2.ToSignature() - if err != nil { - return err - } - bitcoinKey2, err := btcec.ParsePubKey(a.BitcoinKey2[:]) - if err != nil { - return err - } - if !bitcoinSig2.Verify(dataHash, bitcoinKey2) { - return errors.New("can't verify second bitcoin signature") - } - - // Both node signatures attached should indeed be a valid signature - // over the selected digest of the channel announcement signature. - nodeSig1, err := a.NodeSig1.ToSignature() - if err != nil { - return err - } - nodeKey1, err := btcec.ParsePubKey(a.NodeID1[:]) - if err != nil { - return err - } - if !nodeSig1.Verify(dataHash, nodeKey1) { - return errors.New("can't verify data in first node signature") - } - - nodeSig2, err := a.NodeSig2.ToSignature() - if err != nil { - return err - } - nodeKey2, err := btcec.ParsePubKey(a.NodeID2[:]) - if err != nil { - return err - } - if !nodeSig2.Verify(dataHash, nodeKey2) { - return errors.New("can't verify data in second node signature") - } - - return nil - -} - // ValidateNodeAnn validates the node announcement by ensuring that the // attached signature is needed a signature of the node announcement under the // specified node public key. diff --git a/netann/channel_announcement.go b/netann/channel_announcement.go index 4bc7669d2..3731f0b24 100644 --- a/netann/channel_announcement.go +++ b/netann/channel_announcement.go @@ -2,7 +2,10 @@ package netann import ( "bytes" + "errors" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/lnwire" ) @@ -84,3 +87,75 @@ func CreateChanAnnouncement(chanProof *models.ChannelAuthProof, return chanAnn, edge1Ann, edge2Ann, nil } + +// ValidateChannelAnn validates the channel announcement message and checks +// that node signatures covers the announcement message, and that the bitcoin +// signatures covers the node keys. +func ValidateChannelAnn(a *lnwire.ChannelAnnouncement1) error { + // First, we'll compute the digest (h) which is to be signed by each of + // the keys included within the node announcement message. This hash + // digest includes all the keys, so the (up to 4 signatures) will + // attest to the validity of each of the keys. + data, err := a.DataToSign() + if err != nil { + return err + } + dataHash := chainhash.DoubleHashB(data) + + // First we'll verify that the passed bitcoin key signature is indeed a + // signature over the computed hash digest. + bitcoinSig1, err := a.BitcoinSig1.ToSignature() + if err != nil { + return err + } + bitcoinKey1, err := btcec.ParsePubKey(a.BitcoinKey1[:]) + if err != nil { + return err + } + if !bitcoinSig1.Verify(dataHash, bitcoinKey1) { + return errors.New("can't verify first bitcoin signature") + } + + // If that checks out, then we'll verify that the second bitcoin + // signature is a valid signature of the bitcoin public key over hash + // digest as well. + bitcoinSig2, err := a.BitcoinSig2.ToSignature() + if err != nil { + return err + } + bitcoinKey2, err := btcec.ParsePubKey(a.BitcoinKey2[:]) + if err != nil { + return err + } + if !bitcoinSig2.Verify(dataHash, bitcoinKey2) { + return errors.New("can't verify second bitcoin signature") + } + + // Both node signatures attached should indeed be a valid signature + // over the selected digest of the channel announcement signature. + nodeSig1, err := a.NodeSig1.ToSignature() + if err != nil { + return err + } + nodeKey1, err := btcec.ParsePubKey(a.NodeID1[:]) + if err != nil { + return err + } + if !nodeSig1.Verify(dataHash, nodeKey1) { + return errors.New("can't verify data in first node signature") + } + + nodeSig2, err := a.NodeSig2.ToSignature() + if err != nil { + return err + } + nodeKey2, err := btcec.ParsePubKey(a.NodeID2[:]) + if err != nil { + return err + } + if !nodeSig2.Verify(dataHash, nodeKey2) { + return errors.New("can't verify data in second node signature") + } + + return nil +}