@@ -13,6 +13,7 @@ import (
1313 "github.com/lightningnetwork/lnd/input"
1414 "github.com/lightningnetwork/lnd/lnwire"
1515 "github.com/lightningnetwork/lnd/routing/route"
16+ "github.com/lightningnetwork/lnd/tlv"
1617)
1718
1819// ChannelEdgeInfo represents a fully authenticated channel along with all its
@@ -256,6 +257,59 @@ func NewV2Channel(chanID uint64, chainHash chainhash.Hash, node1,
256257 return edge , nil
257258}
258259
260+ // ChannelEdgeInfoFromWireAnnouncement constructs a ChannelEdgeInfo from a wire
261+ // channel announcement message.
262+ func ChannelEdgeInfoFromWireAnnouncement (msg lnwire.ChannelAnnouncement ,
263+ proof * ChannelAuthProof ) (* ChannelEdgeInfo , error ) {
264+
265+ switch msg := msg .(type ) {
266+ case * lnwire.ChannelAnnouncement1 :
267+ return NewV1Channel (
268+ msg .ShortChannelID .ToUint64 (), msg .ChainHash ,
269+ msg .NodeID1 , msg .NodeID2 , & ChannelV1Fields {
270+ BitcoinKey1Bytes : msg .BitcoinKey1 ,
271+ BitcoinKey2Bytes : msg .BitcoinKey2 ,
272+ ExtraOpaqueData : msg .ExtraOpaqueData ,
273+ },
274+ WithChanProof (proof ), WithFeatures (msg .Features ),
275+ )
276+
277+ case * lnwire.ChannelAnnouncement2 :
278+ bitcoinKey1 := fn .MapOption (
279+ func (key [33 ]byte ) route.Vertex {
280+ return key
281+ },
282+ )(msg .BitcoinKey1 .ValOpt ())
283+ bitcoinKey2 := fn .MapOption (
284+ func (key [33 ]byte ) route.Vertex {
285+ return key
286+ },
287+ )(msg .BitcoinKey2 .ValOpt ())
288+ merkleRootHash := fn .MapOption (
289+ func (hash [32 ]byte ) chainhash.Hash {
290+ return hash
291+ },
292+ )(msg .MerkleRootHash .ValOpt ())
293+
294+ return NewV2Channel (
295+ msg .ShortChannelID .Val .ToUint64 (), msg .ChainHash .Val ,
296+ msg .NodeID1 .Val , msg .NodeID2 .Val , & ChannelV2Fields {
297+ BitcoinKey1Bytes : bitcoinKey1 ,
298+ BitcoinKey2Bytes : bitcoinKey2 ,
299+ MerkleRootHash : merkleRootHash ,
300+ ExtraSignedFields : msg .ExtraSignedFields ,
301+ },
302+ WithChanProof (proof ), WithFeatures (& msg .Features .Val ),
303+ WithCapacity (btcutil .Amount (msg .Capacity .Val )),
304+ WithChannelPoint (wire .OutPoint (msg .Outpoint .Val )),
305+ )
306+
307+ default :
308+ return nil , fmt .Errorf ("unsupported channel announcement: %T" ,
309+ msg )
310+ }
311+ }
312+
259313// NodeKey1 is the identity public key of the "first" node that was involved in
260314// the creation of this channel. A node is considered "first" if the
261315// lexicographical ordering the its serialized public key is "smaller" than
@@ -377,10 +431,10 @@ func (c *ChannelEdgeInfo) FundingPKScript() ([]byte, error) {
377431 }
378432}
379433
380- // ToChannelAnnouncement converts the ChannelEdgeInfo to a
434+ // toChannelAnnouncement1 converts the ChannelEdgeInfo to a
381435// lnwire.ChannelAnnouncement1 message. Returns an error if AuthProof is nil
382436// or if the version is not v1.
383- func (c * ChannelEdgeInfo ) ToChannelAnnouncement () (
437+ func (c * ChannelEdgeInfo ) toChannelAnnouncement1 () (
384438 * lnwire.ChannelAnnouncement1 , error ) {
385439
386440 // We currently only support v1 channel announcements.
@@ -452,3 +506,84 @@ func (c *ChannelEdgeInfo) ToChannelAnnouncement() (
452506
453507 return chanAnn , nil
454508}
509+
510+ // ToWireAnnouncement converts the ChannelEdgeInfo to a version-aware wire
511+ // channel announcement.
512+ func (c * ChannelEdgeInfo ) ToWireAnnouncement () (
513+ lnwire.ChannelAnnouncement , error ) {
514+
515+ switch c .Version {
516+ case lnwire .GossipVersion1 :
517+ return c .toChannelAnnouncement1 ()
518+
519+ case lnwire .GossipVersion2 :
520+ return c .toChannelAnnouncement2 ()
521+
522+ default :
523+ return nil , fmt .Errorf ("unsupported channel version: %d" ,
524+ c .Version )
525+ }
526+ }
527+
528+ // toChannelAnnouncement2 converts the ChannelEdgeInfo to a
529+ // lnwire.ChannelAnnouncement2 message.
530+ func (c * ChannelEdgeInfo ) toChannelAnnouncement2 () (
531+ * lnwire.ChannelAnnouncement2 , error ) {
532+
533+ // If there's no auth proof, we can't create a full channel
534+ // announcement.
535+ if c .AuthProof == nil {
536+ return nil , fmt .Errorf ("cannot create channel announcement " +
537+ "without auth proof" )
538+ }
539+
540+ if c .AuthProof .Version != lnwire .GossipVersion2 {
541+ return nil , fmt .Errorf ("invalid channel auth proof version: %d" ,
542+ c .AuthProof .Version )
543+ }
544+
545+ sigBytes := c .AuthProof .Sig ()
546+ if len (sigBytes ) == 0 {
547+ return nil , fmt .Errorf ("missing signature for v2 channel " +
548+ "announcement" )
549+ }
550+
551+ sig , err := lnwire .NewSigFromSchnorrRawSignature (sigBytes )
552+ if err != nil {
553+ return nil , err
554+ }
555+
556+ features := lnwire.RawFeatureVector {}
557+ if c .Features != nil && c .Features .RawFeatureVector != nil {
558+ features = * c .Features .RawFeatureVector
559+ }
560+
561+ var chanAnn lnwire.ChannelAnnouncement2
562+ chanAnn .ChainHash .Val = c .ChainHash
563+ chanAnn .Features .Val = features
564+ chanAnn .ShortChannelID .Val = lnwire .NewShortChanIDFromInt (c .ChannelID )
565+ chanAnn .Capacity .Val = uint64 (c .Capacity )
566+ chanAnn .NodeID1 .Val = [33 ]byte (c .NodeKey1Bytes )
567+ chanAnn .NodeID2 .Val = [33 ]byte (c .NodeKey2Bytes )
568+ chanAnn .Outpoint .Val = lnwire .OutPoint (c .ChannelPoint )
569+ chanAnn .Signature .Val = sig
570+ chanAnn .ExtraSignedFields = c .ExtraSignedFields
571+
572+ c .BitcoinKey1Bytes .WhenSome (func (key route.Vertex ) {
573+ btcKey1 := tlv .ZeroRecordT [tlv.TlvType12 , [33 ]byte ]()
574+ btcKey1 .Val = [33 ]byte (key )
575+ chanAnn .BitcoinKey1 = tlv .SomeRecordT (btcKey1 )
576+ })
577+ c .BitcoinKey2Bytes .WhenSome (func (key route.Vertex ) {
578+ btcKey2 := tlv .ZeroRecordT [tlv.TlvType14 , [33 ]byte ]()
579+ btcKey2 .Val = [33 ]byte (key )
580+ chanAnn .BitcoinKey2 = tlv .SomeRecordT (btcKey2 )
581+ })
582+ c .MerkleRootHash .WhenSome (func (hash chainhash.Hash ) {
583+ merkleRoot := tlv .ZeroRecordT [tlv.TlvType16 , [32 ]byte ]()
584+ merkleRoot .Val = [32 ]byte (hash )
585+ chanAnn .MerkleRootHash = tlv .SomeRecordT (merkleRoot )
586+ })
587+
588+ return & chanAnn , nil
589+ }
0 commit comments