2020-03-17 16:25:02 -07:00
|
|
|
package netann
|
|
|
|
|
|
|
|
import (
|
2025-01-29 11:15:37 +02:00
|
|
|
"bytes"
|
2022-01-20 15:01:44 -08:00
|
|
|
"image/color"
|
2020-03-17 16:25:02 -07:00
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
|
2025-01-29 11:15:37 +02:00
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/go-errors/errors"
|
2021-09-23 16:54:30 +02:00
|
|
|
"github.com/lightningnetwork/lnd/keychain"
|
2020-03-17 16:25:02 -07:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet"
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NodeAnnModifier is a closure that makes in-place modifications to an
|
|
|
|
// lnwire.NodeAnnouncement.
|
|
|
|
type NodeAnnModifier func(*lnwire.NodeAnnouncement)
|
|
|
|
|
2022-01-08 12:16:42 -08:00
|
|
|
// NodeAnnSetAlias is a functional option that sets the alias of the
|
2022-01-20 15:04:04 -08:00
|
|
|
// given node announcement.
|
2022-01-08 12:16:42 -08:00
|
|
|
func NodeAnnSetAlias(alias lnwire.NodeAlias) func(*lnwire.NodeAnnouncement) {
|
|
|
|
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
|
|
|
nodeAnn.Alias = alias
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 16:25:02 -07:00
|
|
|
// NodeAnnSetAddrs is a functional option that allows updating the addresses of
|
|
|
|
// the given node announcement.
|
|
|
|
func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement) {
|
|
|
|
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
|
|
|
nodeAnn.Addresses = addrs
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-20 15:01:44 -08:00
|
|
|
// NodeAnnSetColor is a functional option that sets the color of the
|
2022-01-20 15:04:04 -08:00
|
|
|
// given node announcement.
|
2022-01-20 15:01:44 -08:00
|
|
|
func NodeAnnSetColor(newColor color.RGBA) func(*lnwire.NodeAnnouncement) {
|
|
|
|
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
|
|
|
nodeAnn.RGBColor = newColor
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-02 15:56:04 -08:00
|
|
|
// NodeAnnSetFeatures is a functional option that allows updating the features of
|
|
|
|
// the given node announcement.
|
|
|
|
func NodeAnnSetFeatures(features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement) {
|
|
|
|
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
|
|
|
nodeAnn.Features = features
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 16:25:02 -07:00
|
|
|
// NodeAnnSetTimestamp is a functional option that sets the timestamp of the
|
|
|
|
// announcement to the current time, or increments it if the timestamp is
|
|
|
|
// already in the future.
|
|
|
|
func NodeAnnSetTimestamp(nodeAnn *lnwire.NodeAnnouncement) {
|
|
|
|
newTimestamp := uint32(time.Now().Unix())
|
|
|
|
if newTimestamp <= nodeAnn.Timestamp {
|
|
|
|
// Increment the prior value to ensure the timestamp
|
|
|
|
// monotonically increases, otherwise the announcement won't
|
|
|
|
// propagate.
|
|
|
|
newTimestamp = nodeAnn.Timestamp + 1
|
|
|
|
}
|
|
|
|
nodeAnn.Timestamp = newTimestamp
|
|
|
|
}
|
|
|
|
|
2023-04-03 09:43:46 +02:00
|
|
|
// SignNodeAnnouncement signs the lnwire.NodeAnnouncement provided, which
|
|
|
|
// should be the most recent, valid update, otherwise the timestamp may not
|
|
|
|
// monotonically increase from the prior.
|
2020-03-17 16:25:02 -07:00
|
|
|
func SignNodeAnnouncement(signer lnwallet.MessageSigner,
|
2023-04-03 09:43:46 +02:00
|
|
|
keyLoc keychain.KeyLocator, nodeAnn *lnwire.NodeAnnouncement) error {
|
2020-03-17 16:25:02 -07:00
|
|
|
|
|
|
|
// Create the DER-encoded ECDSA signature over the message digest.
|
2021-09-23 16:54:30 +02:00
|
|
|
sig, err := SignAnnouncement(signer, keyLoc, nodeAnn)
|
2020-03-17 16:25:02 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the DER-encoded signature into a fixed-size 64-byte array.
|
|
|
|
nodeAnn.Signature, err = lnwire.NewSigFromSignature(sig)
|
|
|
|
return err
|
|
|
|
}
|
2025-01-29 11:15:37 +02:00
|
|
|
|
|
|
|
// 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[:])
|
|
|
|
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
|
|
|
|
}
|