Merge pull request #1738 from joostjager/validation
payment failure message with attached channel_update not validated
This commit is contained in:
6 files changed
+409
-186
No files matched your search
@@ -1,146 +0,0 @@
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/go-errors/errors"
|
||||
"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.ChannelAnnouncement) 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[:], btcec.S256())
|
||||
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[:], btcec.S256())
|
||||
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[:], btcec.S256())
|
||||
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[:], btcec.S256())
|
||||
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.
|
||||
func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
|
||||
// Reconstruct the data of announcement which should be covered by the
|
||||
// signature so we can verify the signature shortly below
|
||||
data, err := a.DataToSign()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeSig, err := a.Signature.ToSignature()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nodeKey, err := btcec.ParsePubKey(a.NodeID[:], btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finally ensure that the passed signature is valid, if not we'll
|
||||
// return an error so this node announcement can be rejected.
|
||||
dataHash := chainhash.DoubleHashB(data)
|
||||
if !nodeSig.Verify(dataHash, nodeKey) {
|
||||
var msgBuf bytes.Buffer
|
||||
if _, err := lnwire.WriteMessage(&msgBuf, a, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return errors.Errorf("signature on NodeAnnouncement(%x) is "+
|
||||
"invalid: %x", nodeKey.SerializeCompressed(),
|
||||
msgBuf.Bytes())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateChannelUpdateAnn validates the channel update announcement by
|
||||
// checking that the included signature covers he announcement and has been
|
||||
// signed by the node's private key.
|
||||
func ValidateChannelUpdateAnn(pubKey *btcec.PublicKey,
|
||||
a *lnwire.ChannelUpdate) error {
|
||||
|
||||
data, err := a.DataToSign()
|
||||
if err != nil {
|
||||
return errors.Errorf("unable to reconstruct message: %v", err)
|
||||
}
|
||||
dataHash := chainhash.DoubleHashB(data)
|
||||
|
||||
nodeSig, err := a.Signature.ToSignature()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !nodeSig.Verify(dataHash, pubKey) {
|
||||
return errors.Errorf("invalid signature for channel "+
|
||||
"update %v", spew.Sdump(a))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1520,7 +1520,7 @@ func (d *AuthenticatedGossiper) processRejectedEdge(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = ValidateChannelAnn(chanAnn)
|
||||
err = routing.ValidateChannelAnn(chanAnn)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("assembled channel announcement proof "+
|
||||
"for shortChanID=%v isn't valid: %v",
|
||||
@@ -1598,7 +1598,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := ValidateNodeAnn(msg); err != nil {
|
||||
if err := routing.ValidateNodeAnn(msg); err != nil {
|
||||
err := fmt.Errorf("unable to validate "+
|
||||
"node announcement: %v", err)
|
||||
log.Error(err)
|
||||
@@ -1701,7 +1701,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
||||
// formed.
|
||||
var proof *channeldb.ChannelAuthProof
|
||||
if nMsg.isRemote {
|
||||
if err := ValidateChannelAnn(msg); err != nil {
|
||||
if err := routing.ValidateChannelAnn(msg); err != nil {
|
||||
err := fmt.Errorf("unable to validate "+
|
||||
"announcement: %v", err)
|
||||
d.rejectMtx.Lock()
|
||||
@@ -1993,7 +1993,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
||||
// Validate the channel announcement with the expected public
|
||||
// key, In the case of an invalid channel , we'll return an
|
||||
// error to the caller and exit early.
|
||||
if err := ValidateChannelUpdateAnn(pubKey, msg); err != nil {
|
||||
if err := routing.ValidateChannelUpdateAnn(pubKey, msg); err != nil {
|
||||
rErr := fmt.Errorf("unable to validate channel "+
|
||||
"update announcement for short_chan_id=%v: %v",
|
||||
spew.Sdump(msg.ShortChannelID), err)
|
||||
@@ -2297,7 +2297,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
||||
|
||||
// With all the necessary components assembled validate the
|
||||
// full channel announcement proof.
|
||||
if err := ValidateChannelAnn(chanAnn); err != nil {
|
||||
if err := routing.ValidateChannelAnn(chanAnn); err != nil {
|
||||
err := fmt.Errorf("channel announcement proof "+
|
||||
"for short_chan_id=%v isn't valid: %v",
|
||||
shortChanID, err)
|
||||
@@ -2505,7 +2505,7 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
||||
|
||||
// To ensure that our signature is valid, we'll verify it ourself
|
||||
// before committing it to the slice returned.
|
||||
err = ValidateChannelUpdateAnn(d.selfKey, chanUpdate)
|
||||
err = routing.ValidateChannelUpdateAnn(d.selfKey, chanUpdate)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("generated invalid channel "+
|
||||
"update sig: %v", err)
|
||||
|
||||
Reference in new issue
Block a user