d884efea29
This commit modifies the login of sent/recv’d wire messages in trace mode in order utilize the more detailed, and automatically generated logging statements using pure spew.Sdump. In order to avoid the spammy messages due to spew printing the btcec.S256() curve paramter within wire messages with public keys, we introduce a new logging function to unset the curve paramter to it isn’t printed in its entirety. To insure we don’t run into any panics as a result of a nil pointer defense, we now copy the public keys during the funding process so we don’t run into a panic due to modifying a pointer to the same object.
233 lines
4.7 KiB
Go
233 lines
4.7 KiB
Go
package lnwire
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net"
|
|
|
|
"github.com/go-errors/errors"
|
|
"github.com/roasbeef/btcd/btcec"
|
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
|
)
|
|
|
|
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
|
|
|
|
if err := a.Alias.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := a.DataToSign()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dataHash := chainhash.DoubleHashB(data)
|
|
if !a.Signature.Verify(dataHash, a.NodeID) {
|
|
return errors.New("can't check the node annoucement signature")
|
|
}
|
|
|
|
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
|
|
}
|