216 lines
4.4 KiB
Go
216 lines
4.4 KiB
Go
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
|
|
}
|