mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 09:48:19 +01:00
152 lines
4.6 KiB
Go
152 lines
4.6 KiB
Go
package models
|
|
|
|
import (
|
|
"fmt"
|
|
"image/color"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
)
|
|
|
|
// LightningNode represents an individual vertex/node within the channel graph.
|
|
// A node is connected to other nodes by one or more channel edges emanating
|
|
// from it. As the graph is directed, a node will also have an incoming edge
|
|
// attached to it for each outgoing edge.
|
|
type LightningNode struct {
|
|
// PubKeyBytes is the raw bytes of the public key of the target node.
|
|
PubKeyBytes [33]byte
|
|
pubKey *btcec.PublicKey
|
|
|
|
// HaveNodeAnnouncement indicates whether we received a node
|
|
// announcement for this particular node. If true, the remaining fields
|
|
// will be set, if false only the PubKey is known for this node.
|
|
HaveNodeAnnouncement bool
|
|
|
|
// LastUpdate is the last time the vertex information for this node has
|
|
// been updated.
|
|
LastUpdate time.Time
|
|
|
|
// Address is the TCP address this node is reachable over.
|
|
Addresses []net.Addr
|
|
|
|
// Color is the selected color for the node.
|
|
Color color.RGBA
|
|
|
|
// Alias is a nick-name for the node. The alias can be used to confirm
|
|
// a node's identity or to serve as a short ID for an address book.
|
|
Alias string
|
|
|
|
// AuthSigBytes is the raw signature under the advertised public key
|
|
// which serves to authenticate the attributes announced by this node.
|
|
AuthSigBytes []byte
|
|
|
|
// Features is the list of protocol features supported by this node.
|
|
Features *lnwire.FeatureVector
|
|
|
|
// ExtraOpaqueData is the set of data that was appended to this
|
|
// message, some of which we may not actually know how to iterate or
|
|
// parse. By holding onto this data, we ensure that we're able to
|
|
// properly validate the set of signatures that cover these new fields,
|
|
// and ensure we're able to make upgrades to the network in a forwards
|
|
// compatible manner.
|
|
ExtraOpaqueData []byte
|
|
|
|
// TODO(roasbeef): discovery will need storage to keep it's last IP
|
|
// address and re-announce if interface changes?
|
|
|
|
// TODO(roasbeef): add update method and fetch?
|
|
}
|
|
|
|
// PubKey is the node's long-term identity public key. This key will be used to
|
|
// authenticated any advertisements/updates sent by the node.
|
|
//
|
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
|
// to fully deserialize the pubkey if absolutely necessary.
|
|
func (l *LightningNode) PubKey() (*btcec.PublicKey, error) {
|
|
if l.pubKey != nil {
|
|
return l.pubKey, nil
|
|
}
|
|
|
|
key, err := btcec.ParsePubKey(l.PubKeyBytes[:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
l.pubKey = key
|
|
|
|
return key, nil
|
|
}
|
|
|
|
// AuthSig is a signature under the advertised public key which serves to
|
|
// authenticate the attributes announced by this node.
|
|
//
|
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
|
// to fully deserialize the signature if absolutely necessary.
|
|
func (l *LightningNode) AuthSig() (*ecdsa.Signature, error) {
|
|
return ecdsa.ParseSignature(l.AuthSigBytes)
|
|
}
|
|
|
|
// AddPubKey is a setter-link method that can be used to swap out the public
|
|
// key for a node.
|
|
func (l *LightningNode) AddPubKey(key *btcec.PublicKey) {
|
|
l.pubKey = key
|
|
copy(l.PubKeyBytes[:], key.SerializeCompressed())
|
|
}
|
|
|
|
// NodeAnnouncement retrieves the latest node announcement of the node.
|
|
func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
|
error) {
|
|
|
|
if !l.HaveNodeAnnouncement {
|
|
return nil, fmt.Errorf("node does not have node announcement")
|
|
}
|
|
|
|
alias, err := lnwire.NewNodeAlias(l.Alias)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nodeAnn := &lnwire.NodeAnnouncement{
|
|
Features: l.Features.RawFeatureVector,
|
|
NodeID: l.PubKeyBytes,
|
|
RGBColor: l.Color,
|
|
Alias: alias,
|
|
Addresses: l.Addresses,
|
|
Timestamp: uint32(l.LastUpdate.Unix()),
|
|
ExtraOpaqueData: l.ExtraOpaqueData,
|
|
}
|
|
|
|
if !signed {
|
|
return nodeAnn, nil
|
|
}
|
|
|
|
sig, err := lnwire.NewSigFromECDSARawSignature(l.AuthSigBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nodeAnn.Signature = sig
|
|
|
|
return nodeAnn, nil
|
|
}
|
|
|
|
// NodeFromWireAnnouncement creates a LightningNode instance from an
|
|
// lnwire.NodeAnnouncement message.
|
|
func NodeFromWireAnnouncement(msg *lnwire.NodeAnnouncement) *LightningNode {
|
|
timestamp := time.Unix(int64(msg.Timestamp), 0)
|
|
features := lnwire.NewFeatureVector(msg.Features, lnwire.Features)
|
|
|
|
return &LightningNode{
|
|
HaveNodeAnnouncement: true,
|
|
LastUpdate: timestamp,
|
|
Addresses: msg.Addresses,
|
|
PubKeyBytes: msg.NodeID,
|
|
Alias: msg.Alias.String(),
|
|
AuthSigBytes: msg.Signature.ToSignatureBytes(),
|
|
Features: features,
|
|
Color: msg.RGBColor,
|
|
ExtraOpaqueData: msg.ExtraOpaqueData,
|
|
}
|
|
}
|