lnd/lnwire/node_announcement.go

216 lines
4.4 KiB
Go
Raw Normal View History

package lnwire
import (
"bytes"
"io"
"net"
"github.com/go-errors/errors"
"github.com/roasbeef/btcd/btcec"
)
var (
startPort uint16 = 1024
endPort uint16 = 49151
aliasSpecLen = 21
)
// RGB is used to represent the color.
type RGB struct {
red uint8
green uint8
blue uint8
}
// Alias a hex encoded UTF-8 string that may be displayed as an alternative to
// the node's ID. Notice that aliases are not unique and may be freely chosen
// by the node operators.
type Alias struct {
data [32]byte
aliasLen int
}
// NewAlias create the alias from string and also checks spec requirements.
func NewAlias(s string) (Alias, error) {
data := []byte(s)
return newAlias(data)
}
func newAlias(data []byte) (Alias, error) {
var a [32]byte
aliasEnd := len(data)
for data[aliasEnd-1] == 0 && aliasEnd > 0 {
aliasEnd--
}
copy(a[:aliasEnd], data[:aliasEnd])
return Alias{
data: a,
aliasLen: aliasEnd,
}, nil
}
func (a *Alias) String() string {
return string(a.data[:a.aliasLen])
}
// Validate check that alias data length is lower than spec size.
func (a *Alias) Validate() error {
nonzero := len(a.data)
for a.data[nonzero-1] == 0 && nonzero > 0 {
nonzero--
}
if nonzero > aliasSpecLen {
return errors.New("alias should be less then 21 bytes")
}
return nil
}
// NodeAnnouncement message is used to announce the presence of a lightning node
// and signal that the node is accepting incoming connections.
type NodeAnnouncement struct {
// Signature is used to prove the ownership of node id.
Signature *btcec.Signature
// Timestamp allows ordering in the case of multiple announcements.
Timestamp uint32
// Address includes two specification fields: 'ipv6' and 'port' on which
// the node is accepting incoming connections.
Address *net.TCPAddr
// NodeID is a public key which is used as node identification.
NodeID *btcec.PublicKey
// RGBColor is used to customize their node's appearance in maps and graphs
RGBColor RGB
// pad is used to reserve to additional bytes for future usage.
pad uint16
// Alias is used to customize their node's appearance in maps and graphs
Alias Alias
}
// A compile time check to ensure NodeAnnouncement implements the
// lnwire.Message interface.
var _ Message = (*NodeAnnouncement)(nil)
// Validate performs any necessary sanity checks to ensure all fields present
// on the NodeAnnouncement are valid.
//
// This is part of the lnwire.Message interface.
func (a *NodeAnnouncement) Validate() error {
// TODO(roasbeef): move validation to discovery service
return nil
}
// Decode deserializes a serialized NodeAnnouncement stored in the
// passed io.Reader observing the specified protocol version.
//
// This is part of the lnwire.Message interface.
func (c *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
err := readElements(r,
&c.Signature,
&c.Timestamp,
&c.Address,
&c.NodeID,
&c.RGBColor,
&c.pad,
&c.Alias,
)
if err != nil {
return err
}
return nil
}
// Encode serializes the target NodeAnnouncement into the passed
// io.Writer observing the protocol version specified.
//
// This is part of the lnwire.Message interface.
func (c *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
err := writeElements(w,
c.Signature,
c.Timestamp,
c.Address,
c.NodeID,
c.RGBColor,
c.pad,
c.Alias,
)
if err != nil {
return err
}
return nil
}
// Command returns the integer uniquely identifying this message type on the
// wire.
//
// This is part of the lnwire.Message interface.
func (c *NodeAnnouncement) Command() uint32 {
return CmdNodeAnnoucmentMessage
}
// MaxPayloadLength returns the maximum allowed payload size for this message
// observing the specified protocol version.
//
// This is part of the lnwire.Message interface.
func (c *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 {
var length uint32
// Signature - 64 bytes
length += 64
// Timestamp - 4 bytes
length += 4
// Ipv6 - 16 bytes
length += 16
// Port - 4 bytes
length += 4
// NodeID - 33 bytes
length += 33
// RGBColor - 3 bytes
length += 3
// pad - 2 bytes
length += 2
// Alias - 32 bytes
length += 32
// 158
return length
}
// dataToSign...
func (c *NodeAnnouncement) DataToSign() ([]byte, error) {
// We should not include the signatures itself.
var w bytes.Buffer
err := writeElements(&w,
c.Timestamp,
c.Address,
c.NodeID,
c.RGBColor,
c.pad,
c.Alias,
)
if err != nil {
return nil, err
}
return w.Bytes(), nil
}