mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
220 lines
4.7 KiB
Go
220 lines
4.7 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
|
|
|
|
rawAlias := data
|
|
if len(data) > aliasSpecLen {
|
|
rawAlias = data[:aliasSpecLen]
|
|
}
|
|
|
|
aliasEnd := len(rawAlias)
|
|
for rawAlias[aliasEnd-1] == 0 && aliasEnd > 0 {
|
|
aliasEnd--
|
|
}
|
|
|
|
copy(a[:aliasEnd], rawAlias[: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 also to signal that the node is accepting incoming connections.
|
|
// Each NodeAnnouncement authenticating the advertised information within the
|
|
// announcement via a signature using the advertised node pubkey.
|
|
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
|
|
|
|
// TODO(roasbeef): add the global features here
|
|
|
|
// 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 (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
|
|
return readElements(r,
|
|
&a.Signature,
|
|
&a.Timestamp,
|
|
&a.Address,
|
|
&a.NodeID,
|
|
&a.RGBColor,
|
|
&a.pad,
|
|
&a.Alias,
|
|
)
|
|
}
|
|
|
|
// Encode serializes the target NodeAnnouncement into the passed io.Writer
|
|
// observing the protocol version specified.
|
|
//
|
|
// This is part of the lnwire.Message interface.
|
|
func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
|
|
return writeElements(w,
|
|
a.Signature,
|
|
a.Timestamp,
|
|
a.Address,
|
|
a.NodeID,
|
|
a.RGBColor,
|
|
a.pad,
|
|
a.Alias,
|
|
)
|
|
}
|
|
|
|
// Command returns the integer uniquely identifying this message type on the
|
|
// wire.
|
|
//
|
|
// This is part of the lnwire.Message interface.
|
|
func (a *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 (a *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 returns the part of the message that should be signed.
|
|
func (a *NodeAnnouncement) DataToSign() ([]byte, error) {
|
|
|
|
// We should not include the signatures itself.
|
|
var w bytes.Buffer
|
|
err := writeElements(&w,
|
|
a.Timestamp,
|
|
a.Address,
|
|
a.NodeID,
|
|
a.RGBColor,
|
|
a.pad,
|
|
a.Alias,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return w.Bytes(), nil
|
|
}
|