github.com/decred/dcrlnd@v0.7.6/channeldb/migration/lnwire21/node_announcement.go (about) 1 package lnwire 2 3 import ( 4 "bytes" 5 "fmt" 6 "image/color" 7 "io" 8 "io/ioutil" 9 "net" 10 "unicode/utf8" 11 ) 12 13 // ErrUnknownAddrType is an error returned if we encounter an unknown address 14 // type when parsing addresses. 15 type ErrUnknownAddrType struct { 16 addrType addressType 17 } 18 19 // Error returns a human readable string describing the error. 20 // 21 // NOTE: implements the error interface. 22 func (e ErrUnknownAddrType) Error() string { 23 return fmt.Sprintf("unknown address type: %v", e.addrType) 24 } 25 26 // ErrInvalidNodeAlias is an error returned if a node alias we parse on the 27 // wire is invalid, as in it has non UTF-8 characters. 28 type ErrInvalidNodeAlias struct{} 29 30 // Error returns a human readable string describing the error. 31 // 32 // NOTE: implements the error interface. 33 func (e ErrInvalidNodeAlias) Error() string { 34 return "node alias has non-utf8 characters" 35 } 36 37 // NodeAlias is a hex encoded UTF-8 string that may be displayed as an 38 // alternative to the node's ID. Notice that aliases are not unique and may be 39 // freely chosen by the node operators. 40 type NodeAlias [32]byte 41 42 // NewNodeAlias creates a new instance of a NodeAlias. Verification is 43 // performed on the passed string to ensure it meets the alias requirements. 44 func NewNodeAlias(s string) (NodeAlias, error) { 45 var n NodeAlias 46 47 if len(s) > 32 { 48 return n, fmt.Errorf("alias too large: max is %v, got %v", 32, 49 len(s)) 50 } 51 52 if !utf8.ValidString(s) { 53 return n, &ErrInvalidNodeAlias{} 54 } 55 56 copy(n[:], []byte(s)) 57 return n, nil 58 } 59 60 // String returns a utf8 string representation of the alias bytes. 61 func (n NodeAlias) String() string { 62 // Trim trailing zero-bytes for presentation 63 return string(bytes.Trim(n[:], "\x00")) 64 } 65 66 // NodeAnnouncement message is used to announce the presence of a Lightning 67 // node and also to signal that the node is accepting incoming connections. 68 // Each NodeAnnouncement authenticating the advertised information within the 69 // announcement via a signature using the advertised node pubkey. 70 type NodeAnnouncement struct { 71 // Signature is used to prove the ownership of node id. 72 Signature Sig 73 74 // Features is the list of protocol features this node supports. 75 Features *RawFeatureVector 76 77 // Timestamp allows ordering in the case of multiple announcements. 78 Timestamp uint32 79 80 // NodeID is a public key which is used as node identification. 81 NodeID [33]byte 82 83 // RGBColor is used to customize their node's appearance in maps and 84 // graphs 85 RGBColor color.RGBA 86 87 // Alias is used to customize their node's appearance in maps and 88 // graphs 89 Alias NodeAlias 90 91 // Address includes two specification fields: 'ipv6' and 'port' on 92 // which the node is accepting incoming connections. 93 Addresses []net.Addr 94 95 // ExtraOpaqueData is the set of data that was appended to this 96 // message, some of which we may not actually know how to iterate or 97 // parse. By holding onto this data, we ensure that we're able to 98 // properly validate the set of signatures that cover these new fields, 99 // and ensure we're able to make upgrades to the network in a forwards 100 // compatible manner. 101 ExtraOpaqueData []byte 102 } 103 104 // A compile time check to ensure NodeAnnouncement implements the 105 // lnwire.Message interface. 106 var _ Message = (*NodeAnnouncement)(nil) 107 108 // Decode deserializes a serialized NodeAnnouncement stored in the passed 109 // io.Reader observing the specified protocol version. 110 // 111 // This is part of the lnwire.Message interface. 112 func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error { 113 err := ReadElements(r, 114 &a.Signature, 115 &a.Features, 116 &a.Timestamp, 117 &a.NodeID, 118 &a.RGBColor, 119 &a.Alias, 120 &a.Addresses, 121 ) 122 if err != nil { 123 return err 124 } 125 126 // Now that we've read out all the fields that we explicitly know of, 127 // we'll collect the remainder into the ExtraOpaqueData field. If there 128 // aren't any bytes, then we'll snip off the slice to avoid carrying 129 // around excess capacity. 130 a.ExtraOpaqueData, err = ioutil.ReadAll(r) 131 if err != nil { 132 return err 133 } 134 if len(a.ExtraOpaqueData) == 0 { 135 a.ExtraOpaqueData = nil 136 } 137 138 return nil 139 } 140 141 // Encode serializes the target NodeAnnouncement into the passed io.Writer 142 // observing the protocol version specified. 143 func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error { 144 return WriteElements(w, 145 a.Signature, 146 a.Features, 147 a.Timestamp, 148 a.NodeID, 149 a.RGBColor, 150 a.Alias, 151 a.Addresses, 152 a.ExtraOpaqueData, 153 ) 154 } 155 156 // MsgType returns the integer uniquely identifying this message type on the 157 // wire. 158 // 159 // This is part of the lnwire.Message interface. 160 func (a *NodeAnnouncement) MsgType() MessageType { 161 return MsgNodeAnnouncement 162 } 163 164 // MaxPayloadLength returns the maximum allowed payload size for this message 165 // observing the specified protocol version. 166 // 167 // This is part of the lnwire.Message interface. 168 func (a *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 { 169 return 65533 170 } 171 172 // DataToSign returns the part of the message that should be signed. 173 func (a *NodeAnnouncement) DataToSign() ([]byte, error) { 174 175 // We should not include the signatures itself. 176 var w bytes.Buffer 177 err := WriteElements(&w, 178 a.Features, 179 a.Timestamp, 180 a.NodeID, 181 a.RGBColor, 182 a.Alias[:], 183 a.Addresses, 184 a.ExtraOpaqueData, 185 ) 186 if err != nil { 187 return nil, err 188 } 189 190 return w.Bytes(), nil 191 }