@@ -10,6 +10,8 @@ import (
1010 "github.com/lightningnetwork/lnd/fn/v2"
1111 "github.com/lightningnetwork/lnd/lnwire"
1212 "github.com/lightningnetwork/lnd/routing/route"
13+ "github.com/lightningnetwork/lnd/tlv"
14+ "github.com/lightningnetwork/lnd/tor"
1315)
1416
1517// Node represents an individual vertex/node within the channel graph.
@@ -22,6 +24,7 @@ type Node struct {
2224
2325 // PubKeyBytes is the raw bytes of the public key of the target node.
2426 PubKeyBytes [33 ]byte
27+ pubKey * btcec.PublicKey
2528
2629 // LastUpdate is the last time the vertex information for this node has
2730 // been updated.
@@ -185,20 +188,51 @@ func (n *Node) HaveAnnouncement() bool {
185188
186189// PubKey is the node's long-term identity public key. This key will be used to
187190// authenticated any advertisements/updates sent by the node.
191+ //
192+ // NOTE: By having this method to access the attribute, we ensure we only need
193+ // to fully deserialize the pubkey if absolutely necessary.
188194func (n * Node ) PubKey () (* btcec.PublicKey , error ) {
189- return btcec .ParsePubKey (n .PubKeyBytes [:])
195+ if n .pubKey != nil {
196+ return n .pubKey , nil
197+ }
198+
199+ key , err := btcec .ParsePubKey (n .PubKeyBytes [:])
200+ if err != nil {
201+ return nil , err
202+ }
203+ n .pubKey = key
204+
205+ return key , nil
190206}
191207
192- // NodeAnnouncement retrieves the latest node announcement of the node.
193- func (n * Node ) NodeAnnouncement (signed bool ) (* lnwire.NodeAnnouncement1 ,
208+ // NodeAnnouncement reconstructs the wire node announcement for this node.
209+ // If signed is true, the returned announcement will include the node's
210+ // signature. Returns an error if signed is true but no signature is stored.
211+ func (n * Node ) NodeAnnouncement (signed bool ) (lnwire.NodeAnnouncement ,
194212 error ) {
195213
196- // Error out if we request the signed announcement, but we don't have
197- // a signature for this announcement.
198- if ! n .HaveAnnouncement () && signed {
214+ if signed && ! n .HaveAnnouncement () {
199215 return nil , fmt .Errorf ("node does not have node announcement" )
200216 }
201217
218+ switch n .Version {
219+ case lnwire .GossipVersion1 :
220+ return n .toNodeAnnouncement1 (signed )
221+
222+ case lnwire .GossipVersion2 :
223+ return n .toNodeAnnouncement2 (signed )
224+
225+ default :
226+ return nil , fmt .Errorf ("unsupported node version: %d" ,
227+ n .Version )
228+ }
229+ }
230+
231+ // toNodeAnnouncement1 constructs a v1 node announcement from the node's
232+ // stored fields.
233+ func (n * Node ) toNodeAnnouncement1 (signed bool ) (* lnwire.NodeAnnouncement1 ,
234+ error ) {
235+
202236 alias , err := lnwire .NewNodeAlias (n .Alias .UnwrapOr ("" ))
203237 if err != nil {
204238 return nil , err
@@ -218,12 +252,97 @@ func (n *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement1,
218252 return nodeAnn , nil
219253 }
220254
221- sig , err := lnwire .NewSigFromECDSARawSignature (n .AuthSigBytes )
255+ nodeAnn .Signature , err = lnwire .NewSigFromECDSARawSignature (
256+ n .AuthSigBytes ,
257+ )
222258 if err != nil {
223259 return nil , err
224260 }
225261
226- nodeAnn .Signature = sig
262+ return nodeAnn , nil
263+ }
264+
265+ // toNodeAnnouncement2 constructs a v2 node announcement from the node's
266+ // stored fields.
267+ func (n * Node ) toNodeAnnouncement2 (signed bool ) (* lnwire.NodeAnnouncement2 ,
268+ error ) {
269+
270+ nodeAnn := & lnwire.NodeAnnouncement2 {
271+ Features : tlv.NewRecordT [tlv.TlvType0 ](
272+ * n .Features .RawFeatureVector ,
273+ ),
274+ BlockHeight : tlv.NewPrimitiveRecord [tlv.TlvType2 ](
275+ n .LastBlockHeight ,
276+ ),
277+ NodeID : tlv.NewPrimitiveRecord [tlv.TlvType4 , [33 ]byte ](
278+ n .PubKeyBytes ,
279+ ),
280+ ExtraSignedFields : n .ExtraSignedFields ,
281+ }
282+
283+ n .Alias .WhenSome (func (s string ) {
284+ aliasRecord := tlv .ZeroRecordT [tlv.TlvType3 , lnwire.NodeAlias2 ]()
285+ aliasRecord .Val = lnwire .NodeAlias2 (s )
286+ nodeAnn .Alias = tlv .SomeRecordT (aliasRecord )
287+ })
288+
289+ n .Color .WhenSome (func (rgba color.RGBA ) {
290+ colorRecord := tlv .ZeroRecordT [tlv.TlvType1 , lnwire.Color ]()
291+ colorRecord .Val = lnwire .Color (rgba )
292+ nodeAnn .Color = tlv .SomeRecordT (colorRecord )
293+ })
294+
295+ // Categorise addresses by type for the separate TLV fields.
296+ var (
297+ ipv4 lnwire.IPV4Addrs
298+ ipv6 lnwire.IPV6Addrs
299+ torV3 lnwire.TorV3Addrs
300+ )
301+ for _ , addr := range n .Addresses {
302+ switch a := addr .(type ) {
303+ case * net.TCPAddr :
304+ if a .IP .To4 () != nil {
305+ ipv4 = append (ipv4 , a )
306+ } else {
307+ ipv6 = append (ipv6 , a )
308+ }
309+
310+ case * tor.OnionAddr :
311+ torV3 = append (torV3 , a )
312+
313+ case * lnwire.DNSAddress :
314+ nodeAnn .DNSHostName = tlv .SomeRecordT (
315+ tlv.NewRecordT [tlv.TlvType11 ](* a ),
316+ )
317+ }
318+ }
319+ if len (ipv4 ) > 0 {
320+ nodeAnn .IPV4Addrs = tlv .SomeRecordT (
321+ tlv.NewRecordT [tlv.TlvType5 ](ipv4 ),
322+ )
323+ }
324+ if len (ipv6 ) > 0 {
325+ nodeAnn .IPV6Addrs = tlv .SomeRecordT (
326+ tlv.NewRecordT [tlv.TlvType7 ](ipv6 ),
327+ )
328+ }
329+ if len (torV3 ) > 0 {
330+ nodeAnn .TorV3Addrs = tlv .SomeRecordT (
331+ tlv.NewRecordT [tlv.TlvType9 ](torV3 ),
332+ )
333+ }
334+
335+ if ! signed {
336+ return nodeAnn , nil
337+ }
338+
339+ var err error
340+ nodeAnn .Signature .Val , err = lnwire .NewSigFromSchnorrRawSignature (
341+ n .AuthSigBytes ,
342+ )
343+ if err != nil {
344+ return nil , err
345+ }
227346
228347 return nodeAnn , nil
229348}
0 commit comments