github.com/decred/dcrlnd@v0.7.6/routing/ann_validation.go (about)

     1  package routing
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/davecgh/go-spew/spew"
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    10  	"github.com/decred/dcrd/dcrutil/v4"
    11  	"github.com/decred/dcrlnd/lnwire"
    12  	"github.com/go-errors/errors"
    13  )
    14  
    15  // ValidateChannelAnn validates the channel announcement message and checks
    16  // that node signatures covers the announcement message, and that the bitcoin
    17  // signatures covers the node keys.
    18  func ValidateChannelAnn(a *lnwire.ChannelAnnouncement) error {
    19  	// First, we'll compute the digest (h) which is to be signed by each of
    20  	// the keys included within the node announcement message. This hash
    21  	// digest includes all the keys, so the (up to 4 signatures) will
    22  	// attest to the validity of each of the keys.
    23  	data, err := a.DataToSign()
    24  	if err != nil {
    25  		return err
    26  	}
    27  	dataHash := chainhash.HashB(data)
    28  
    29  	// First we'll verify that the passed bitcoin key signature is indeed a
    30  	// signature over the computed hash digest.
    31  	decredSig1, err := a.DecredSig1.ToSignature()
    32  	if err != nil {
    33  		return err
    34  	}
    35  	bitcoinKey1, err := secp256k1.ParsePubKey(a.DecredKey1[:])
    36  	if err != nil {
    37  		return err
    38  	}
    39  	if !decredSig1.Verify(dataHash, bitcoinKey1) {
    40  		return errors.New("can't verify first bitcoin signature")
    41  	}
    42  
    43  	// If that checks out, then we'll verify that the second bitcoin
    44  	// signature is a valid signature of the bitcoin public key over hash
    45  	// digest as well.
    46  	decredSig2, err := a.DecredSig2.ToSignature()
    47  	if err != nil {
    48  		return err
    49  	}
    50  	bitcoinKey2, err := secp256k1.ParsePubKey(a.DecredKey2[:])
    51  	if err != nil {
    52  		return err
    53  	}
    54  	if !decredSig2.Verify(dataHash, bitcoinKey2) {
    55  		return errors.New("can't verify second bitcoin signature")
    56  	}
    57  
    58  	// Both node signatures attached should indeed be a valid signature
    59  	// over the selected digest of the channel announcement signature.
    60  	nodeSig1, err := a.NodeSig1.ToSignature()
    61  	if err != nil {
    62  		return err
    63  	}
    64  	nodeKey1, err := secp256k1.ParsePubKey(a.NodeID1[:])
    65  	if err != nil {
    66  		return err
    67  	}
    68  	if !nodeSig1.Verify(dataHash, nodeKey1) {
    69  		return errors.New("can't verify data in first node signature")
    70  	}
    71  
    72  	nodeSig2, err := a.NodeSig2.ToSignature()
    73  	if err != nil {
    74  		return err
    75  	}
    76  	nodeKey2, err := secp256k1.ParsePubKey(a.NodeID2[:])
    77  	if err != nil {
    78  		return err
    79  	}
    80  	if !nodeSig2.Verify(dataHash, nodeKey2) {
    81  		return errors.New("can't verify data in second node signature")
    82  	}
    83  
    84  	return nil
    85  
    86  }
    87  
    88  // ValidateNodeAnn validates the node announcement by ensuring that the
    89  // attached signature is needed a signature of the node announcement under the
    90  // specified node public key.
    91  func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
    92  	// Reconstruct the data of announcement which should be covered by the
    93  	// signature so we can verify the signature shortly below
    94  	data, err := a.DataToSign()
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	nodeSig, err := a.Signature.ToSignature()
   100  	if err != nil {
   101  		return err
   102  	}
   103  	nodeKey, err := secp256k1.ParsePubKey(a.NodeID[:])
   104  	if err != nil {
   105  		return err
   106  	}
   107  
   108  	// Finally ensure that the passed signature is valid, if not we'll
   109  	// return an error so this node announcement can be rejected.
   110  	dataHash := chainhash.HashB(data)
   111  	if !nodeSig.Verify(dataHash, nodeKey) {
   112  		var msgBuf bytes.Buffer
   113  		if _, err := lnwire.WriteMessage(&msgBuf, a, 0); err != nil {
   114  			return err
   115  		}
   116  
   117  		return errors.Errorf("signature on NodeAnnouncement(%x) is "+
   118  			"invalid: %x", nodeKey.SerializeCompressed(),
   119  			msgBuf.Bytes())
   120  	}
   121  
   122  	return nil
   123  }
   124  
   125  // ValidateChannelUpdateAnn validates the channel update announcement by
   126  // checking (1) that the included signature covers the announcement and has
   127  // been signed by the node's private key, and (2) that the announcement's
   128  // message flags and optional fields are sane.
   129  func ValidateChannelUpdateAnn(pubKey *secp256k1.PublicKey, capacity dcrutil.Amount,
   130  	a *lnwire.ChannelUpdate) error {
   131  
   132  	if err := validateOptionalFields(capacity, a); err != nil {
   133  		return err
   134  	}
   135  
   136  	return VerifyChannelUpdateSignature(a, pubKey)
   137  }
   138  
   139  // VerifyChannelUpdateSignature verifies that the channel update message was
   140  // signed by the party with the given node public key.
   141  func VerifyChannelUpdateSignature(msg *lnwire.ChannelUpdate,
   142  	pubKey *secp256k1.PublicKey) error {
   143  
   144  	data, err := msg.DataToSign()
   145  	if err != nil {
   146  		return fmt.Errorf("unable to reconstruct message data: %v", err)
   147  	}
   148  	dataHash := chainhash.HashB(data)
   149  
   150  	nodeSig, err := msg.Signature.ToSignature()
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	if !nodeSig.Verify(dataHash, pubKey) {
   156  		return fmt.Errorf("invalid signature for channel update %v",
   157  			spew.Sdump(msg))
   158  	}
   159  
   160  	return nil
   161  }
   162  
   163  // validateOptionalFields validates a channel update's message flags and
   164  // corresponding update fields.
   165  func validateOptionalFields(capacity dcrutil.Amount,
   166  	msg *lnwire.ChannelUpdate) error {
   167  
   168  	if msg.MessageFlags.HasMaxHtlc() {
   169  		maxHtlc := msg.HtlcMaximumMAtoms
   170  		if maxHtlc == 0 || maxHtlc < msg.HtlcMinimumMAtoms {
   171  			return errors.Errorf("invalid max htlc for channel "+
   172  				"update %v", spew.Sdump(msg))
   173  		}
   174  
   175  		// For light clients, the capacity will not be set so we'll skip
   176  		// checking whether the MaxHTLC value respects the channel's
   177  		// capacity.
   178  		capacityMat := lnwire.NewMAtomsFromAtoms(capacity)
   179  		if capacityMat != 0 && maxHtlc > capacityMat {
   180  			return errors.Errorf("max_htlc(%v) for channel "+
   181  				"update greater than capacity(%v)", maxHtlc,
   182  				capacityMat)
   183  		}
   184  	}
   185  
   186  	return nil
   187  }