Merge pull request #10232 from ellemouton/g175MessageFollowup
lnwire: add missing Gossip 1.75 fields and message
This commit is contained in:
32 files changed
+1435
-136
No files matched your search
+12
-11
@@ -244,11 +244,11 @@ type Config struct {
|
|||||||
// FetchSelfAnnouncement retrieves our current node announcement, for
|
// FetchSelfAnnouncement retrieves our current node announcement, for
|
||||||
// use when determining whether we should update our peers about our
|
// use when determining whether we should update our peers about our
|
||||||
// presence in the network.
|
// presence in the network.
|
||||||
FetchSelfAnnouncement func() lnwire.NodeAnnouncement
|
FetchSelfAnnouncement func() lnwire.NodeAnnouncement1
|
||||||
|
|
||||||
// UpdateSelfAnnouncement produces a new announcement for our node with
|
// UpdateSelfAnnouncement produces a new announcement for our node with
|
||||||
// an updated timestamp which can be broadcast to our peers.
|
// an updated timestamp which can be broadcast to our peers.
|
||||||
UpdateSelfAnnouncement func() (lnwire.NodeAnnouncement, error)
|
UpdateSelfAnnouncement func() (lnwire.NodeAnnouncement1, error)
|
||||||
|
|
||||||
// ProofMatureDelta the number of confirmations which is needed before
|
// ProofMatureDelta the number of confirmations which is needed before
|
||||||
// exchange the channel announcement proofs.
|
// exchange the channel announcement proofs.
|
||||||
@@ -1186,7 +1186,7 @@ func (d *deDupedAnnouncements) addMsg(message networkMsg) {
|
|||||||
|
|
||||||
// Node announcements are identified by the Vertex field. Use the
|
// Node announcements are identified by the Vertex field. Use the
|
||||||
// NodeID to create the corresponding Vertex.
|
// NodeID to create the corresponding Vertex.
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
sender := route.NewVertex(message.source)
|
sender := route.NewVertex(message.source)
|
||||||
deDupKey := route.Vertex(msg.NodeID)
|
deDupKey := route.Vertex(msg.NodeID)
|
||||||
|
|
||||||
@@ -1195,7 +1195,8 @@ func (d *deDupedAnnouncements) addMsg(message networkMsg) {
|
|||||||
oldTimestamp := uint32(0)
|
oldTimestamp := uint32(0)
|
||||||
mws, ok := d.nodeAnnouncements[deDupKey]
|
mws, ok := d.nodeAnnouncements[deDupKey]
|
||||||
if ok {
|
if ok {
|
||||||
oldTimestamp = mws.msg.(*lnwire.NodeAnnouncement).Timestamp
|
ann, _ := mws.msg.(*lnwire.NodeAnnouncement1)
|
||||||
|
oldTimestamp = ann.Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard the message if it's old.
|
// Discard the message if it's old.
|
||||||
@@ -1806,7 +1807,7 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(ctx context.Context,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll also check that our NodeAnnouncement is not too old.
|
// We'll also check that our NodeAnnouncement1 is not too old.
|
||||||
currentNodeAnn := d.cfg.FetchSelfAnnouncement()
|
currentNodeAnn := d.cfg.FetchSelfAnnouncement()
|
||||||
timestamp := time.Unix(int64(currentNodeAnn.Timestamp), 0)
|
timestamp := time.Unix(int64(currentNodeAnn.Timestamp), 0)
|
||||||
timeElapsed := now.Sub(timestamp)
|
timeElapsed := now.Sub(timestamp)
|
||||||
@@ -2062,7 +2063,7 @@ func (d *AuthenticatedGossiper) fetchPKScript(chanID lnwire.ShortChannelID) (
|
|||||||
// addNode processes the given node announcement, and adds it to our channel
|
// addNode processes the given node announcement, and adds it to our channel
|
||||||
// graph.
|
// graph.
|
||||||
func (d *AuthenticatedGossiper) addNode(ctx context.Context,
|
func (d *AuthenticatedGossiper) addNode(ctx context.Context,
|
||||||
msg *lnwire.NodeAnnouncement, op ...batch.SchedulerOption) error {
|
msg *lnwire.NodeAnnouncement1, op ...batch.SchedulerOption) error {
|
||||||
|
|
||||||
if err := netann.ValidateNodeAnn(msg); err != nil {
|
if err := netann.ValidateNodeAnn(msg); err != nil {
|
||||||
return fmt.Errorf("unable to validate node announcement: %w",
|
return fmt.Errorf("unable to validate node announcement: %w",
|
||||||
@@ -2153,7 +2154,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(ctx context.Context,
|
|||||||
// A new node announcement has arrived which either presents new
|
// A new node announcement has arrived which either presents new
|
||||||
// information about a node in one of the channels we know about, or a
|
// information about a node in one of the channels we know about, or a
|
||||||
// updating previously advertised information.
|
// updating previously advertised information.
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
return d.handleNodeAnnouncement(ctx, nMsg, msg, schedulerOp)
|
return d.handleNodeAnnouncement(ctx, nMsg, msg, schedulerOp)
|
||||||
|
|
||||||
// A new channel announcement has arrived, this indicates the
|
// A new channel announcement has arrived, this indicates the
|
||||||
@@ -2248,7 +2249,7 @@ func (d *AuthenticatedGossiper) processZombieUpdate(_ context.Context,
|
|||||||
// announcement fields and returns an error if they are invalid to prevent
|
// announcement fields and returns an error if they are invalid to prevent
|
||||||
// forwarding invalid node announcements to our peers.
|
// forwarding invalid node announcements to our peers.
|
||||||
func (d *AuthenticatedGossiper) fetchNodeAnn(ctx context.Context,
|
func (d *AuthenticatedGossiper) fetchNodeAnn(ctx context.Context,
|
||||||
pubKey [33]byte) (*lnwire.NodeAnnouncement, error) {
|
pubKey [33]byte) (*lnwire.NodeAnnouncement1, error) {
|
||||||
|
|
||||||
node, err := d.cfg.Graph.FetchNode(ctx, pubKey)
|
node, err := d.cfg.Graph.FetchNode(ctx, pubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -2478,12 +2479,12 @@ func (d *AuthenticatedGossiper) latestHeight() uint32 {
|
|||||||
|
|
||||||
// handleNodeAnnouncement processes a new node announcement.
|
// handleNodeAnnouncement processes a new node announcement.
|
||||||
func (d *AuthenticatedGossiper) handleNodeAnnouncement(ctx context.Context,
|
func (d *AuthenticatedGossiper) handleNodeAnnouncement(ctx context.Context,
|
||||||
nMsg *networkMsg, nodeAnn *lnwire.NodeAnnouncement,
|
nMsg *networkMsg, nodeAnn *lnwire.NodeAnnouncement1,
|
||||||
ops []batch.SchedulerOption) ([]networkMsg, bool) {
|
ops []batch.SchedulerOption) ([]networkMsg, bool) {
|
||||||
|
|
||||||
timestamp := time.Unix(int64(nodeAnn.Timestamp), 0)
|
timestamp := time.Unix(int64(nodeAnn.Timestamp), 0)
|
||||||
|
|
||||||
log.Debugf("Processing NodeAnnouncement: peer=%v, timestamp=%v, "+
|
log.Debugf("Processing NodeAnnouncement1: peer=%v, timestamp=%v, "+
|
||||||
"node=%x, source=%x", nMsg.peer, timestamp, nodeAnn.NodeID,
|
"node=%x, source=%x", nMsg.peer, timestamp, nodeAnn.NodeID,
|
||||||
nMsg.source.SerializeCompressed())
|
nMsg.source.SerializeCompressed())
|
||||||
|
|
||||||
@@ -2542,7 +2543,7 @@ func (d *AuthenticatedGossiper) handleNodeAnnouncement(ctx context.Context,
|
|||||||
nMsg.err <- nil
|
nMsg.err <- nil
|
||||||
// TODO(roasbeef): get rid of the above
|
// TODO(roasbeef): get rid of the above
|
||||||
|
|
||||||
log.Debugf("Processed NodeAnnouncement: peer=%v, timestamp=%v, "+
|
log.Debugf("Processed NodeAnnouncement1: peer=%v, timestamp=%v, "+
|
||||||
"node=%x, source=%x", nMsg.peer, timestamp, nodeAnn.NodeID,
|
"node=%x, source=%x", nMsg.peer, timestamp, nodeAnn.NodeID,
|
||||||
nMsg.source.SerializeCompressed())
|
nMsg.source.SerializeCompressed())
|
||||||
|
|
||||||
|
|||||||
+15
-14
@@ -493,8 +493,8 @@ func (m *mockNotifier) Stop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type annBatch struct {
|
type annBatch struct {
|
||||||
nodeAnn1 *lnwire.NodeAnnouncement
|
nodeAnn1 *lnwire.NodeAnnouncement1
|
||||||
nodeAnn2 *lnwire.NodeAnnouncement
|
nodeAnn2 *lnwire.NodeAnnouncement1
|
||||||
|
|
||||||
chanAnn *lnwire.ChannelAnnouncement1
|
chanAnn *lnwire.ChannelAnnouncement1
|
||||||
|
|
||||||
@@ -577,8 +577,8 @@ func (ctx *testCtx) createAnnouncements(blockHeight uint32, key1,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNodeAnnouncement(priv *btcec.PrivateKey,
|
func createNodeAnnouncement(priv *btcec.PrivateKey, timestamp uint32,
|
||||||
timestamp uint32, extraBytes ...[]byte) (*lnwire.NodeAnnouncement, error) {
|
extraBytes ...[]byte) (*lnwire.NodeAnnouncement1, error) {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
k := hex.EncodeToString(priv.Serialize())
|
k := hex.EncodeToString(priv.Serialize())
|
||||||
@@ -587,7 +587,7 @@ func createNodeAnnouncement(priv *btcec.PrivateKey,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
a := &lnwire.NodeAnnouncement{
|
a := &lnwire.NodeAnnouncement1{
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
@@ -966,15 +966,15 @@ func createTestCtx(t *testing.T, startHeight uint32, isChanPeer bool) (
|
|||||||
c := make(chan struct{})
|
c := make(chan struct{})
|
||||||
return c
|
return c
|
||||||
},
|
},
|
||||||
FetchSelfAnnouncement: func() lnwire.NodeAnnouncement {
|
FetchSelfAnnouncement: func() lnwire.NodeAnnouncement1 {
|
||||||
return lnwire.NodeAnnouncement{
|
return lnwire.NodeAnnouncement1{
|
||||||
Timestamp: testTimestamp,
|
Timestamp: testTimestamp,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdateSelfAnnouncement: func() (lnwire.NodeAnnouncement,
|
UpdateSelfAnnouncement: func() (lnwire.NodeAnnouncement1,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
return lnwire.NodeAnnouncement{
|
return lnwire.NodeAnnouncement1{
|
||||||
Timestamp: testTimestamp,
|
Timestamp: testTimestamp,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
@@ -2285,7 +2285,7 @@ func TestForwardPrivateNodeAnnouncement(t *testing.T) {
|
|||||||
case <-time.After(2 * trickleDelay):
|
case <-time.After(2 * trickleDelay):
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, we'll attempt to forward the NodeAnnouncement for the same node
|
// Now, we'll attempt to forward the NodeAnnouncement1 for the same node
|
||||||
// by opening a public channel on the network. We'll create a
|
// by opening a public channel on the network. We'll create a
|
||||||
// ChannelAnnouncement and hand it off to the gossiper in order to
|
// ChannelAnnouncement and hand it off to the gossiper in order to
|
||||||
// process it.
|
// process it.
|
||||||
@@ -2312,8 +2312,9 @@ func TestForwardPrivateNodeAnnouncement(t *testing.T) {
|
|||||||
t.Fatal("gossiper should have broadcast the channel announcement")
|
t.Fatal("gossiper should have broadcast the channel announcement")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll recreate the NodeAnnouncement with an updated timestamp to
|
// We'll recreate the NodeAnnouncement1 with an updated timestamp to
|
||||||
// prevent a stale update. The NodeAnnouncement should now be forwarded.
|
// prevent a stale update. The NodeAnnouncement1 should now be
|
||||||
|
// forwarded.
|
||||||
nodeAnn, err = createNodeAnnouncement(remoteKeyPriv1, timestamp+1)
|
nodeAnn, err = createNodeAnnouncement(remoteKeyPriv1, timestamp+1)
|
||||||
require.NoError(t, err, "unable to create node announcement")
|
require.NoError(t, err, "unable to create node announcement")
|
||||||
|
|
||||||
@@ -2897,7 +2898,7 @@ func TestExtraDataChannelUpdateValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TestExtraDataNodeAnnouncementValidation tests that we're able to properly
|
// TestExtraDataNodeAnnouncementValidation tests that we're able to properly
|
||||||
// validate a NodeAnnouncement that includes opaque bytes that we don't
|
// validate a NodeAnnouncement1 that includes opaque bytes that we don't
|
||||||
// currently know of.
|
// currently know of.
|
||||||
func TestExtraDataNodeAnnouncementValidation(t *testing.T) {
|
func TestExtraDataNodeAnnouncementValidation(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@@ -3044,7 +3045,7 @@ func TestRetransmit(t *testing.T) {
|
|||||||
chanAnn++
|
chanAnn++
|
||||||
case *lnwire.ChannelUpdate1:
|
case *lnwire.ChannelUpdate1:
|
||||||
chanUpd++
|
chanUpd++
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
nodeAnn++
|
nodeAnn++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1653,7 +1653,7 @@ func (g *GossipSyncer) FilterGossipMsgs(ctx context.Context,
|
|||||||
|
|
||||||
// Similarly, we only send node announcements if the update
|
// Similarly, we only send node announcements if the update
|
||||||
// timestamp ifs between our set gossip filter time range.
|
// timestamp ifs between our set gossip filter time range.
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
if passesFilter(msg.Timestamp) {
|
if passesFilter(msg.Timestamp) {
|
||||||
msgsToSend = append(msgsToSend, msg)
|
msgsToSend = append(msgsToSend, msg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,10 +249,14 @@ func TestGossipSyncerFilterGossipMsgsNoHorizon(t *testing.T) {
|
|||||||
// through the gossiper to the target peer.
|
// through the gossiper to the target peer.
|
||||||
msgs := []msgWithSenders{
|
msgs := []msgWithSenders{
|
||||||
{
|
{
|
||||||
msg: &lnwire.NodeAnnouncement{Timestamp: uint32(time.Now().Unix())},
|
msg: &lnwire.NodeAnnouncement1{
|
||||||
|
Timestamp: uint32(time.Now().Unix()),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: &lnwire.NodeAnnouncement{Timestamp: uint32(time.Now().Unix())},
|
msg: &lnwire.NodeAnnouncement1{
|
||||||
|
Timestamp: uint32(time.Now().Unix()),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,15 +312,21 @@ func TestGossipSyncerFilterGossipMsgsAllInMemory(t *testing.T) {
|
|||||||
msgs := []msgWithSenders{
|
msgs := []msgWithSenders{
|
||||||
{
|
{
|
||||||
// Node ann above horizon.
|
// Node ann above horizon.
|
||||||
msg: &lnwire.NodeAnnouncement{Timestamp: unixStamp(25001)},
|
msg: &lnwire.NodeAnnouncement1{
|
||||||
|
Timestamp: unixStamp(25001),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Node ann below horizon.
|
// Node ann below horizon.
|
||||||
msg: &lnwire.NodeAnnouncement{Timestamp: unixStamp(5)},
|
msg: &lnwire.NodeAnnouncement1{
|
||||||
|
Timestamp: unixStamp(5),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Node ann above horizon.
|
// Node ann above horizon.
|
||||||
msg: &lnwire.NodeAnnouncement{Timestamp: unixStamp(999999)},
|
msg: &lnwire.NodeAnnouncement1{
|
||||||
|
Timestamp: unixStamp(999999),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Ann tuple below horizon.
|
// Ann tuple below horizon.
|
||||||
@@ -737,7 +747,7 @@ func TestGossipSyncerReplyShortChanIDs(t *testing.T) {
|
|||||||
ShortChannelID: lnwire.NewShortChanIDFromInt(20),
|
ShortChannelID: lnwire.NewShortChanIDFromInt(20),
|
||||||
Timestamp: unixStamp(999999),
|
Timestamp: unixStamp(999999),
|
||||||
},
|
},
|
||||||
&lnwire.NodeAnnouncement{Timestamp: unixStamp(25001)},
|
&lnwire.NodeAnnouncement1{Timestamp: unixStamp(25001)},
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll then craft a reply to the upcoming query for all the matching
|
// We'll then craft a reply to the upcoming query for all the matching
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) (JobID,
|
|||||||
populateDependencies(msg.ShortChannelID.String(), childJobID)
|
populateDependencies(msg.ShortChannelID.String(), childJobID)
|
||||||
|
|
||||||
return childJobID, nil
|
return childJobID, nil
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
childJobID := JobID(v.idCtr.Add(1))
|
childJobID := JobID(v.idCtr.Add(1))
|
||||||
populateDependencies(
|
populateDependencies(
|
||||||
route.Vertex(msg.NodeID).String(), childJobID,
|
route.Vertex(msg.NodeID).String(), childJobID,
|
||||||
@@ -242,7 +242,7 @@ func (v *ValidationBarrier) WaitForParents(childJobID JobID,
|
|||||||
v.Lock()
|
v.Lock()
|
||||||
|
|
||||||
switch msg := job.(type) {
|
switch msg := job.(type) {
|
||||||
// Any ChannelUpdate or NodeAnnouncement jobs will need to wait on the
|
// Any ChannelUpdate or NodeAnnouncement1 jobs will need to wait on the
|
||||||
// completion of any active ChannelAnnouncement jobs related to them.
|
// completion of any active ChannelAnnouncement jobs related to them.
|
||||||
case *lnwire.ChannelUpdate1:
|
case *lnwire.ChannelUpdate1:
|
||||||
annID = msg.ShortChannelID.String()
|
annID = msg.ShortChannelID.String()
|
||||||
@@ -258,7 +258,7 @@ func (v *ValidationBarrier) WaitForParents(childJobID JobID,
|
|||||||
jobDesc = fmt.Sprintf("job=lnwire.ChannelUpdate, scid=%v",
|
jobDesc = fmt.Sprintf("job=lnwire.ChannelUpdate, scid=%v",
|
||||||
msg.ShortChannelID.ToUint64())
|
msg.ShortChannelID.ToUint64())
|
||||||
|
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
annID = route.Vertex(msg.NodeID).String()
|
annID = route.Vertex(msg.NodeID).String()
|
||||||
|
|
||||||
parentJobIDs, ok = v.jobDependencies[childJobID]
|
parentJobIDs, ok = v.jobDependencies[childJobID]
|
||||||
@@ -269,7 +269,7 @@ func (v *ValidationBarrier) WaitForParents(childJobID JobID,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
jobDesc = fmt.Sprintf("job=lnwire.NodeAnnouncement, pub=%s",
|
jobDesc = fmt.Sprintf("job=lnwire.NodeAnnouncement1, pub=%s",
|
||||||
route.Vertex(msg.NodeID))
|
route.Vertex(msg.NodeID))
|
||||||
|
|
||||||
// Other types of jobs can be executed immediately, so we'll just
|
// Other types of jobs can be executed immediately, so we'll just
|
||||||
@@ -446,7 +446,7 @@ func (v *ValidationBarrier) SignalDependents(job interface{}, id JobID) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
// Remove child job info.
|
// Remove child job info.
|
||||||
return removeJob(route.Vertex(msg.NodeID).String(), id, true)
|
return removeJob(route.Vertex(msg.NodeID).String(), id, true)
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ func TestValidationBarrierQuit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TestValidationBarrierParentJobsClear tests that creating two parent jobs for
|
// TestValidationBarrierParentJobsClear tests that creating two parent jobs for
|
||||||
// ChannelUpdate / NodeAnnouncement will pause child jobs until the set of
|
// ChannelUpdate / NodeAnnouncement1 will pause child jobs until the set of
|
||||||
// parent jobs has cleared.
|
// parent jobs has cleared.
|
||||||
func TestValidationBarrierParentJobsClear(t *testing.T) {
|
func TestValidationBarrierParentJobsClear(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@@ -230,14 +230,14 @@ func TestValidationBarrierParentJobsClear(t *testing.T) {
|
|||||||
parentID3, err := barrier.InitJobDependencies(ann3)
|
parentID3, err := barrier.InitJobDependencies(ann3)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create the ChannelUpdate & NodeAnnouncement messages.
|
// Create the ChannelUpdate & NodeAnnouncement1 messages.
|
||||||
upd1 := &lnwire.ChannelUpdate1{
|
upd1 := &lnwire.ChannelUpdate1{
|
||||||
ShortChannelID: sharedScid,
|
ShortChannelID: sharedScid,
|
||||||
}
|
}
|
||||||
childID1, err := barrier.InitJobDependencies(upd1)
|
childID1, err := barrier.InitJobDependencies(upd1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
node1 := &lnwire.NodeAnnouncement{
|
node1 := &lnwire.NodeAnnouncement1{
|
||||||
NodeID: sharedNodeID,
|
NodeID: sharedNodeID,
|
||||||
}
|
}
|
||||||
childID2, err := barrier.InitJobDependencies(node1)
|
childID2, err := barrier.InitJobDependencies(node1)
|
||||||
|
|||||||
+5
-5
@@ -398,7 +398,7 @@ type Config struct {
|
|||||||
// CurrentNodeAnnouncement should return the latest, fully signed node
|
// CurrentNodeAnnouncement should return the latest, fully signed node
|
||||||
// announcement from the backing Lightning Network node with a fresh
|
// announcement from the backing Lightning Network node with a fresh
|
||||||
// timestamp.
|
// timestamp.
|
||||||
CurrentNodeAnnouncement func() (lnwire.NodeAnnouncement, error)
|
CurrentNodeAnnouncement func() (lnwire.NodeAnnouncement1, error)
|
||||||
|
|
||||||
// SendAnnouncement is used by the FundingManager to send announcement
|
// SendAnnouncement is used by the FundingManager to send announcement
|
||||||
// messages to the Gossiper to possibly broadcast to the greater
|
// messages to the Gossiper to possibly broadcast to the greater
|
||||||
@@ -3757,8 +3757,8 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
|
|||||||
shortChanID *lnwire.ShortChannelID) error {
|
shortChanID *lnwire.ShortChannelID) error {
|
||||||
|
|
||||||
// If this channel is not meant to be announced to the greater network,
|
// If this channel is not meant to be announced to the greater network,
|
||||||
// we'll only send our NodeAnnouncement to our counterparty to ensure we
|
// we'll only send our NodeAnnouncement1 to our counterparty to ensure
|
||||||
// don't leak any of our information.
|
// we don't leak any of our information.
|
||||||
announceChan := completeChan.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
announceChan := completeChan.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||||
if !announceChan {
|
if !announceChan {
|
||||||
log.Debugf("Will not announce private channel %v.",
|
log.Debugf("Will not announce private channel %v.",
|
||||||
@@ -3779,7 +3779,7 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
|
|||||||
completeChan.FundingOutpoint,
|
completeChan.FundingOutpoint,
|
||||||
)
|
)
|
||||||
pubKey := peer.PubKey()
|
pubKey := peer.PubKey()
|
||||||
log.Debugf("Sending our NodeAnnouncement for "+
|
log.Debugf("Sending our NodeAnnouncement1 for "+
|
||||||
"ChannelID(%v) to %x", chanID, pubKey)
|
"ChannelID(%v) to %x", chanID, pubKey)
|
||||||
|
|
||||||
// TODO(halseth): make reliable. If the peer is not online this
|
// TODO(halseth): make reliable. If the peer is not online this
|
||||||
@@ -4724,7 +4724,7 @@ func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey,
|
|||||||
graph.ErrIgnored) {
|
graph.ErrIgnored) {
|
||||||
|
|
||||||
log.Debugf("Graph rejected "+
|
log.Debugf("Graph rejected "+
|
||||||
"NodeAnnouncement: %v", err)
|
"NodeAnnouncement1: %v", err)
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("Unable to send node "+
|
log.Errorf("Unable to send node "+
|
||||||
"announcement: %v", err)
|
"announcement: %v", err)
|
||||||
|
|||||||
+14
-13
@@ -485,10 +485,10 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
|||||||
}
|
}
|
||||||
return errChan
|
return errChan
|
||||||
},
|
},
|
||||||
CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement,
|
CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement1,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
return lnwire.NodeAnnouncement{}, nil
|
return lnwire.NodeAnnouncement1{}, nil
|
||||||
},
|
},
|
||||||
TempChanIDSeed: chanIDSeed,
|
TempChanIDSeed: chanIDSeed,
|
||||||
FindChannel: func(node *btcec.PublicKey,
|
FindChannel: func(node *btcec.PublicKey,
|
||||||
@@ -660,10 +660,10 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
|
|||||||
}
|
}
|
||||||
return errChan
|
return errChan
|
||||||
},
|
},
|
||||||
CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement,
|
CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement1,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
return lnwire.NodeAnnouncement{}, nil
|
return lnwire.NodeAnnouncement1{}, nil
|
||||||
},
|
},
|
||||||
NotifyWhenOnline: func(peer [33]byte,
|
NotifyWhenOnline: func(peer [33]byte,
|
||||||
connectedChan chan<- lnpeer.Peer) {
|
connectedChan chan<- lnpeer.Peer) {
|
||||||
@@ -1328,9 +1328,9 @@ func assertAnnouncementSignatures(t *testing.T, alice, bob *testNode) {
|
|||||||
// by having the nodes exchange announcement signatures.
|
// by having the nodes exchange announcement signatures.
|
||||||
// Two distinct messages will be sent:
|
// Two distinct messages will be sent:
|
||||||
// 1) AnnouncementSignatures
|
// 1) AnnouncementSignatures
|
||||||
// 2) NodeAnnouncement
|
// 2) NodeAnnouncement1
|
||||||
// These may arrive in no particular order.
|
// These may arrive in no particular order.
|
||||||
// Note that sending the NodeAnnouncement at this point is an
|
// Note that sending the NodeAnnouncement1 at this point is an
|
||||||
// implementation detail, and not something required by the LN spec.
|
// implementation detail, and not something required by the LN spec.
|
||||||
for j, node := range []*testNode{alice, bob} {
|
for j, node := range []*testNode{alice, bob} {
|
||||||
announcements := make([]lnwire.Message, 2)
|
announcements := make([]lnwire.Message, 2)
|
||||||
@@ -1348,7 +1348,7 @@ func assertAnnouncementSignatures(t *testing.T, alice, bob *testNode) {
|
|||||||
switch msg.(type) {
|
switch msg.(type) {
|
||||||
case *lnwire.AnnounceSignatures1:
|
case *lnwire.AnnounceSignatures1:
|
||||||
gotAnnounceSignatures = true
|
gotAnnounceSignatures = true
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
gotNodeAnnouncement = true
|
gotNodeAnnouncement = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1358,7 +1358,8 @@ func assertAnnouncementSignatures(t *testing.T, alice, bob *testNode) {
|
|||||||
j)
|
j)
|
||||||
}
|
}
|
||||||
if !gotNodeAnnouncement {
|
if !gotNodeAnnouncement {
|
||||||
t.Fatalf("did not get NodeAnnouncement from node %d", j)
|
t.Fatalf("did not get NodeAnnouncement1 from node %d",
|
||||||
|
j)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1378,7 +1379,7 @@ func assertNodeAnnSent(t *testing.T, alice, bob *testNode) {
|
|||||||
node.msgChan, time.Second*5,
|
node.msgChan, time.Second*5,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assertType[*lnwire.NodeAnnouncement](t, *nodeAnn)
|
assertType[*lnwire.NodeAnnouncement1](t, *nodeAnn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2959,7 +2960,7 @@ func TestFundingManagerPrivateChannel(t *testing.T) {
|
|||||||
// We should however receive each side's node announcement.
|
// We should however receive each side's node announcement.
|
||||||
select {
|
select {
|
||||||
case msg := <-alice.msgChan:
|
case msg := <-alice.msgChan:
|
||||||
if _, ok := msg.(*lnwire.NodeAnnouncement); !ok {
|
if _, ok := msg.(*lnwire.NodeAnnouncement1); !ok {
|
||||||
t.Fatalf("expected to receive node announcement")
|
t.Fatalf("expected to receive node announcement")
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
@@ -2968,7 +2969,7 @@ func TestFundingManagerPrivateChannel(t *testing.T) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case msg := <-bob.msgChan:
|
case msg := <-bob.msgChan:
|
||||||
if _, ok := msg.(*lnwire.NodeAnnouncement); !ok {
|
if _, ok := msg.(*lnwire.NodeAnnouncement1); !ok {
|
||||||
t.Fatalf("expected to receive node announcement")
|
t.Fatalf("expected to receive node announcement")
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
@@ -3085,7 +3086,7 @@ func TestFundingManagerPrivateRestart(t *testing.T) {
|
|||||||
// We should however receive each side's node announcement.
|
// We should however receive each side's node announcement.
|
||||||
select {
|
select {
|
||||||
case msg := <-alice.msgChan:
|
case msg := <-alice.msgChan:
|
||||||
if _, ok := msg.(*lnwire.NodeAnnouncement); !ok {
|
if _, ok := msg.(*lnwire.NodeAnnouncement1); !ok {
|
||||||
t.Fatalf("expected to receive node announcement")
|
t.Fatalf("expected to receive node announcement")
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
@@ -3094,7 +3095,7 @@ func TestFundingManagerPrivateRestart(t *testing.T) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case msg := <-bob.msgChan:
|
case msg := <-bob.msgChan:
|
||||||
if _, ok := msg.(*lnwire.NodeAnnouncement); !ok {
|
if _, ok := msg.(*lnwire.NodeAnnouncement1); !ok {
|
||||||
t.Fatalf("expected to receive node announcement")
|
t.Fatalf("expected to receive node announcement")
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
|
|||||||
@@ -4754,10 +4754,10 @@ func TestLightningNodePersistence(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Use the raw serialized node announcement message create an
|
// Use the raw serialized node announcement message create an
|
||||||
// lnwire.NodeAnnouncement instance.
|
// lnwire.NodeAnnouncement1 instance.
|
||||||
msg, err := lnwire.ReadMessage(bytes.NewBuffer(nodeAnnBytes), 0)
|
msg, err := lnwire.ReadMessage(bytes.NewBuffer(nodeAnnBytes), 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
na, ok := msg.(*lnwire.NodeAnnouncement)
|
na, ok := msg.(*lnwire.NodeAnnouncement1)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
// Convert the wire message to our internal node representation.
|
// Convert the wire message to our internal node representation.
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ func (l *Node) AddPubKey(key *btcec.PublicKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NodeAnnouncement retrieves the latest node announcement of the node.
|
// NodeAnnouncement retrieves the latest node announcement of the node.
|
||||||
func (l *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
func (l *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement1,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
if !l.HaveNodeAnnouncement {
|
if !l.HaveNodeAnnouncement {
|
||||||
@@ -108,7 +108,7 @@ func (l *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeAnn := &lnwire.NodeAnnouncement{
|
nodeAnn := &lnwire.NodeAnnouncement1{
|
||||||
Features: l.Features.RawFeatureVector,
|
Features: l.Features.RawFeatureVector,
|
||||||
NodeID: l.PubKeyBytes,
|
NodeID: l.PubKeyBytes,
|
||||||
RGBColor: l.Color,
|
RGBColor: l.Color,
|
||||||
@@ -133,8 +133,8 @@ func (l *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NodeFromWireAnnouncement creates a Node instance from an
|
// NodeFromWireAnnouncement creates a Node instance from an
|
||||||
// lnwire.NodeAnnouncement message.
|
// lnwire.NodeAnnouncement1 message.
|
||||||
func NodeFromWireAnnouncement(msg *lnwire.NodeAnnouncement) *Node {
|
func NodeFromWireAnnouncement(msg *lnwire.NodeAnnouncement1) *Node {
|
||||||
timestamp := time.Unix(int64(msg.Timestamp), 0)
|
timestamp := time.Unix(int64(msg.Timestamp), 0)
|
||||||
features := lnwire.NewFeatureVector(msg.Features, lnwire.Features)
|
features := lnwire.NewFeatureVector(msg.Features, lnwire.Features)
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
// GetNodeAnnouncement is used to send our retrieve the current
|
// GetNodeAnnouncement is used to send our retrieve the current
|
||||||
// node announcement information.
|
// node announcement information.
|
||||||
GetNodeAnnouncement func() lnwire.NodeAnnouncement
|
GetNodeAnnouncement func() lnwire.NodeAnnouncement1
|
||||||
|
|
||||||
// ParseAddr parses an address from its string format to a net.Addr.
|
// ParseAddr parses an address from its string format to a net.Addr.
|
||||||
ParseAddr func(addr string) (net.Addr, error)
|
ParseAddr func(addr string) (net.Addr, error)
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ type ChannelAnnouncement2 struct {
|
|||||||
// the funding output is a pure 2-of-2 MuSig aggregate public key.
|
// the funding output is a pure 2-of-2 MuSig aggregate public key.
|
||||||
MerkleRootHash tlv.OptionalRecordT[tlv.TlvType16, [32]byte]
|
MerkleRootHash tlv.OptionalRecordT[tlv.TlvType16, [32]byte]
|
||||||
|
|
||||||
|
// Outpoint is the outpoint of the funding transaction.
|
||||||
|
Outpoint tlv.RecordT[tlv.TlvType18, OutPoint]
|
||||||
|
|
||||||
// Signature is a Schnorr signature over serialised signed-range TLV
|
// Signature is a Schnorr signature over serialised signed-range TLV
|
||||||
// stream of the message.
|
// stream of the message.
|
||||||
Signature tlv.RecordT[tlv.TlvType160, Sig]
|
Signature tlv.RecordT[tlv.TlvType160, Sig]
|
||||||
@@ -81,17 +84,17 @@ func (c *ChannelAnnouncement2) Encode(w *bytes.Buffer, _ uint32) error {
|
|||||||
// NOTE: this is part of the PureTLVMessage interface.
|
// NOTE: this is part of the PureTLVMessage interface.
|
||||||
func (c *ChannelAnnouncement2) AllRecords() []tlv.Record {
|
func (c *ChannelAnnouncement2) AllRecords() []tlv.Record {
|
||||||
recordProducers := append(
|
recordProducers := append(
|
||||||
c.allNonSignatureRecordProducers(), &c.Signature,
|
c.nonSignatureRecordProducers(), &c.Signature,
|
||||||
)
|
)
|
||||||
|
|
||||||
return ProduceRecordsSorted(recordProducers...)
|
return ProduceRecordsSorted(recordProducers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// allNonSignatureRecordProducers returns all the TLV record producers for the
|
// nonSignatureRecordProducers returns all the TLV record producers for the
|
||||||
// message except the signature record producer.
|
// message except the signature record producer.
|
||||||
//
|
//
|
||||||
//nolint:ll
|
//nolint:ll
|
||||||
func (c *ChannelAnnouncement2) allNonSignatureRecordProducers() []tlv.RecordProducer {
|
func (c *ChannelAnnouncement2) nonSignatureRecordProducers() []tlv.RecordProducer {
|
||||||
// The chain-hash record is only included if it is _not_ equal to the
|
// The chain-hash record is only included if it is _not_ equal to the
|
||||||
// bitcoin mainnet genisis block hash.
|
// bitcoin mainnet genisis block hash.
|
||||||
var recordProducers []tlv.RecordProducer
|
var recordProducers []tlv.RecordProducer
|
||||||
@@ -121,6 +124,7 @@ func (c *ChannelAnnouncement2) allNonSignatureRecordProducers() []tlv.RecordProd
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
recordProducers = append(recordProducers, &c.Outpoint)
|
||||||
recordProducers = append(recordProducers, RecordsAsProducers(
|
recordProducers = append(recordProducers, RecordsAsProducers(
|
||||||
tlv.MapToRecords(c.ExtraSignedFields),
|
tlv.MapToRecords(c.ExtraSignedFields),
|
||||||
)...)
|
)...)
|
||||||
@@ -149,6 +153,7 @@ func (c *ChannelAnnouncement2) Decode(r io.Reader, _ uint32) error {
|
|||||||
&btcKey1,
|
&btcKey1,
|
||||||
&btcKey2,
|
&btcKey2,
|
||||||
&merkleRootHash,
|
&merkleRootHash,
|
||||||
|
&c.Outpoint,
|
||||||
&c.Signature,
|
&c.Signature,
|
||||||
)...)
|
)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -202,6 +207,7 @@ func (c *ChannelAnnouncement2) DecodeNonSigTLVRecords(r io.Reader) error {
|
|||||||
&btcKey1,
|
&btcKey1,
|
||||||
&btcKey2,
|
&btcKey2,
|
||||||
&merkleRootHash,
|
&merkleRootHash,
|
||||||
|
&c.Outpoint,
|
||||||
)...)
|
)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -239,7 +245,7 @@ func (c *ChannelAnnouncement2) DecodeNonSigTLVRecords(r io.Reader) error {
|
|||||||
// excludes the signature field.
|
// excludes the signature field.
|
||||||
func (c *ChannelAnnouncement2) EncodeAllNonSigFields(w io.Writer) error {
|
func (c *ChannelAnnouncement2) EncodeAllNonSigFields(w io.Writer) error {
|
||||||
return EncodeRecordsTo(
|
return EncodeRecordsTo(
|
||||||
w, ProduceRecordsSorted(c.allNonSignatureRecordProducers()...),
|
w, ProduceRecordsSorted(c.nonSignatureRecordProducers()...),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,17 @@ func TestChanAnn2EncodeDecode(t *testing.T) {
|
|||||||
0xb3, 0xee, 0x17, 0x2f, 0x7f, 0x16, 0x1, 0xe6, 0x7d, 0x1d, 0xa6,
|
0xb3, 0xee, 0x17, 0x2f, 0x7f, 0x16, 0x1, 0xe6, 0x7d, 0x1d, 0xa6,
|
||||||
0xca, 0xd4, 0xb, 0x54, 0xc4, 0x46, 0x8d, 0x48, 0x23, 0x6c, 0x39,
|
0xca, 0xd4, 0xb, 0x54, 0xc4, 0x46, 0x8d, 0x48, 0x23, 0x6c, 0x39,
|
||||||
|
|
||||||
|
// Outpoint record.
|
||||||
|
0x12, // type (18).
|
||||||
|
0x22, // length (34 bytes).
|
||||||
|
// Hash (32 bytes).
|
||||||
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||||
|
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||||
|
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||||
|
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
// Index (2 bytes).
|
||||||
|
0x30, 0x39, // value: 12345.
|
||||||
|
|
||||||
// Unknown TLV record.
|
// Unknown TLV record.
|
||||||
0x6f, // type.
|
0x6f, // type.
|
||||||
0x2, // length.
|
0x2, // length.
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ type ChannelUpdate2 struct {
|
|||||||
// millionth of a satoshi.
|
// millionth of a satoshi.
|
||||||
FeeProportionalMillionths tlv.RecordT[tlv.TlvType18, uint32]
|
FeeProportionalMillionths tlv.RecordT[tlv.TlvType18, uint32]
|
||||||
|
|
||||||
|
// InboundFee is an optional TLV record that contains the fee
|
||||||
|
// information for incoming HTLCs.
|
||||||
|
// TODO(elle): assign normal tlv type?
|
||||||
|
InboundFee tlv.OptionalRecordT[tlv.TlvType55555, Fee]
|
||||||
|
|
||||||
// Signature is used to validate the announced data and prove the
|
// Signature is used to validate the announced data and prove the
|
||||||
// ownership of node id.
|
// ownership of node id.
|
||||||
Signature tlv.RecordT[tlv.TlvType160, Sig]
|
Signature tlv.RecordT[tlv.TlvType160, Sig]
|
||||||
@@ -102,12 +107,13 @@ func (c *ChannelUpdate2) Decode(r io.Reader, _ uint32) error {
|
|||||||
var (
|
var (
|
||||||
chainHash = tlv.ZeroRecordT[tlv.TlvType0, [32]byte]()
|
chainHash = tlv.ZeroRecordT[tlv.TlvType0, [32]byte]()
|
||||||
secondPeer = tlv.ZeroRecordT[tlv.TlvType8, TrueBoolean]()
|
secondPeer = tlv.ZeroRecordT[tlv.TlvType8, TrueBoolean]()
|
||||||
|
inboundFee = tlv.ZeroRecordT[tlv.TlvType55555, Fee]()
|
||||||
)
|
)
|
||||||
typeMap, err := tlvRecords.ExtractRecords(
|
typeMap, err := tlvRecords.ExtractRecords(
|
||||||
&chainHash, &c.ShortChannelID, &c.BlockHeight, &c.DisabledFlags,
|
&chainHash, &c.ShortChannelID, &c.BlockHeight, &c.DisabledFlags,
|
||||||
&secondPeer, &c.CLTVExpiryDelta, &c.HTLCMinimumMsat,
|
&secondPeer, &c.CLTVExpiryDelta, &c.HTLCMinimumMsat,
|
||||||
&c.HTLCMaximumMsat, &c.FeeBaseMsat,
|
&c.HTLCMaximumMsat, &c.FeeBaseMsat,
|
||||||
&c.FeeProportionalMillionths,
|
&c.FeeProportionalMillionths, &inboundFee,
|
||||||
&c.Signature,
|
&c.Signature,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -149,6 +155,11 @@ func (c *ChannelUpdate2) Decode(r io.Reader, _ uint32) error {
|
|||||||
c.FeeProportionalMillionths.Val = defaultFeeProportionalMillionths //nolint:ll
|
c.FeeProportionalMillionths.Val = defaultFeeProportionalMillionths //nolint:ll
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the inbound fee was encoded, set it.
|
||||||
|
if _, ok := typeMap[c.InboundFee.TlvType()]; ok {
|
||||||
|
c.InboundFee = tlv.SomeRecordT(inboundFee)
|
||||||
|
}
|
||||||
|
|
||||||
c.ExtraSignedFields = ExtraSignedFieldsFromTypeMap(typeMap)
|
c.ExtraSignedFields = ExtraSignedFieldsFromTypeMap(typeMap)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -207,6 +218,10 @@ func (c *ChannelUpdate2) AllRecords() []tlv.Record {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.InboundFee.WhenSome(func(r tlv.RecordT[tlv.TlvType55555, Fee]) {
|
||||||
|
recordProducers = append(recordProducers, &r)
|
||||||
|
})
|
||||||
|
|
||||||
recordProducers = append(recordProducers, RecordsAsProducers(
|
recordProducers = append(recordProducers, RecordsAsProducers(
|
||||||
tlv.MapToRecords(c.ExtraSignedFields),
|
tlv.MapToRecords(c.ExtraSignedFields),
|
||||||
)...)
|
)...)
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -86,3 +90,70 @@ func ValidateDNSAddr(hostname string, port uint16) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record returns a TLV record that can be used to encode/decode the DNSAddress.
|
||||||
|
//
|
||||||
|
// NOTE: this is part of the tlv.RecordProducer interface.
|
||||||
|
func (d *DNSAddress) Record() tlv.Record {
|
||||||
|
sizeFunc := func() uint64 {
|
||||||
|
// Hostname length + 2 bytes for port.
|
||||||
|
return uint64(len(d.Hostname) + 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.MakeDynamicRecord(
|
||||||
|
0, d, sizeFunc, dnsAddressEncoder, dnsAddressDecoder,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsAddressEncoder is a TLV encoder for DNSAddress.
|
||||||
|
func dnsAddressEncoder(w io.Writer, val any, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*DNSAddress); ok {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
// Write the hostname as raw bytes (no length prefix for TLV).
|
||||||
|
if _, err := buf.WriteString(v.Hostname); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the port as 2 bytes.
|
||||||
|
err := WriteUint16(&buf, v.Port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(buf.Bytes())
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "DNSAddress")
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsAddressDecoder is a TLV decoder for DNSAddress.
|
||||||
|
func dnsAddressDecoder(r io.Reader, val any, _ *[8]byte,
|
||||||
|
l uint64) error {
|
||||||
|
|
||||||
|
if v, ok := val.(*DNSAddress); ok {
|
||||||
|
if l < 2 {
|
||||||
|
return fmt.Errorf("DNS address must be at least 2 " +
|
||||||
|
"bytes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read hostname (all bytes except last 2).
|
||||||
|
hostnameLen := l - 2
|
||||||
|
hostnameBytes := make([]byte, hostnameLen)
|
||||||
|
if _, err := io.ReadFull(r, hostnameBytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Hostname = string(hostnameBytes)
|
||||||
|
|
||||||
|
// Read port (last 2 bytes).
|
||||||
|
if err := ReadElement(r, &v.Port); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValidateDNSAddr(v.Hostname, v.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForDecodingErr(val, "DNSAddress", l, 0)
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"pgregory.net/rapid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestValidateDNSAddr tests hostname and port validation per BOLT #7.
|
// TestValidateDNSAddr tests hostname and port validation per BOLT #7.
|
||||||
@@ -85,3 +88,112 @@ func TestValidateDNSAddr(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDNSAddressTLVEncoding tests the TLV encoding and decoding of DNSAddress
|
||||||
|
// structs using the ExtraOpaqueData interface.
|
||||||
|
func TestDNSAddressTLVEncoding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testDNSAddr := DNSAddress{
|
||||||
|
Hostname: "lightning.example.com",
|
||||||
|
Port: 9000,
|
||||||
|
}
|
||||||
|
|
||||||
|
var extraData ExtraOpaqueData
|
||||||
|
require.NoError(t, extraData.PackRecords(&testDNSAddr))
|
||||||
|
|
||||||
|
var decodedDNSAddr DNSAddress
|
||||||
|
tlvs, err := extraData.ExtractRecords(&decodedDNSAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Contains(t, tlvs, tlv.Type(0))
|
||||||
|
require.Equal(t, testDNSAddr, decodedDNSAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDNSAddressRecord tests the TLV Record interface of DNSAddress
|
||||||
|
// by directly encoding and decoding using the Record method.
|
||||||
|
func TestDNSAddressRecord(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testDNSAddr := DNSAddress{
|
||||||
|
Hostname: "lightning.example.com",
|
||||||
|
Port: 9000,
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
record := testDNSAddr.Record()
|
||||||
|
require.NoError(t, record.Encode(&buf))
|
||||||
|
|
||||||
|
var decodedDNSAddr DNSAddress
|
||||||
|
decodedRecord := decodedDNSAddr.Record()
|
||||||
|
require.NoError(t, decodedRecord.Decode(&buf, uint64(buf.Len())))
|
||||||
|
|
||||||
|
require.Equal(t, testDNSAddr, decodedDNSAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDNSAddressInvalidDecoding tests error cases during TLV decoding.
|
||||||
|
func TestDNSAddressInvalidDecoding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
data []byte
|
||||||
|
errMsg string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "too short (only 1 byte)",
|
||||||
|
data: []byte{0x61},
|
||||||
|
errMsg: "DNS address must be at least 2 bytes",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty data",
|
||||||
|
data: []byte{},
|
||||||
|
errMsg: "DNS address must be at least 2 bytes",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
var dnsAddr DNSAddress
|
||||||
|
record := dnsAddr.Record()
|
||||||
|
|
||||||
|
buf := bytes.NewReader(tc.data)
|
||||||
|
err := record.Decode(buf, uint64(len(tc.data)))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, tc.errMsg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDNSAddressProperty uses property-based testing to verify that DNSAddress
|
||||||
|
// TLV encoding and decoding is correct for random DNSAddress values.
|
||||||
|
func TestDNSAddressProperty(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
scenario := func(t *rapid.T) {
|
||||||
|
// Generate a random valid hostname.
|
||||||
|
hostname := genValidHostname(t)
|
||||||
|
|
||||||
|
// Generate a random port (excluding 0 which is invalid).
|
||||||
|
port := rapid.Uint16Range(1, 65535).Draw(t, "port")
|
||||||
|
|
||||||
|
dnsAddr := DNSAddress{
|
||||||
|
Hostname: hostname,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
record := dnsAddr.Record()
|
||||||
|
err := record.Encode(&buf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var decodedDNSAddr DNSAddress
|
||||||
|
decodedRecord := decodedDNSAddr.Record()
|
||||||
|
err = decodedRecord.Decode(&buf, uint64(buf.Len()))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, dnsAddr, decodedDNSAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
rapid.Check(t, scenario)
|
||||||
|
}
|
||||||
+28
-4
@@ -220,10 +220,10 @@ func FuzzNodeAnnouncement(f *testing.F) {
|
|||||||
// can be represented by different underlying bytes. Instead, we
|
// can be represented by different underlying bytes. Instead, we
|
||||||
// compare the normalized string representation of each address.
|
// compare the normalized string representation of each address.
|
||||||
assertEq := func(t *testing.T, x, y any) {
|
assertEq := func(t *testing.T, x, y any) {
|
||||||
require.IsType(t, &NodeAnnouncement{}, x)
|
require.IsType(t, &NodeAnnouncement1{}, x)
|
||||||
first, _ := x.(*NodeAnnouncement)
|
first, _ := x.(*NodeAnnouncement1)
|
||||||
require.IsType(t, &NodeAnnouncement{}, y)
|
require.IsType(t, &NodeAnnouncement1{}, y)
|
||||||
second, _ := y.(*NodeAnnouncement)
|
second, _ := y.(*NodeAnnouncement1)
|
||||||
|
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t, len(first.Addresses), len(second.Addresses),
|
t, len(first.Addresses), len(second.Addresses),
|
||||||
@@ -244,6 +244,30 @@ func FuzzNodeAnnouncement(f *testing.F) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FuzzNodeAnnouncement2(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
// We can't use require.Equal for Features, since we consider
|
||||||
|
// the empty map and nil to be equivalent.
|
||||||
|
assertEq := func(t *testing.T, x, y any) {
|
||||||
|
require.IsType(t, &NodeAnnouncement2{}, x)
|
||||||
|
first, _ := x.(*NodeAnnouncement2)
|
||||||
|
require.IsType(t, &NodeAnnouncement2{}, y)
|
||||||
|
second, _ := y.(*NodeAnnouncement2)
|
||||||
|
|
||||||
|
require.True(
|
||||||
|
t,
|
||||||
|
first.Features.Val.Equals(&second.Features.Val),
|
||||||
|
)
|
||||||
|
first.Features.Val = *NewRawFeatureVector()
|
||||||
|
second.Features.Val = *NewRawFeatureVector()
|
||||||
|
|
||||||
|
require.Equal(t, first, second)
|
||||||
|
}
|
||||||
|
|
||||||
|
wireMsgHarnessCustom(t, data, MsgNodeAnnouncement2, assertEq)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func FuzzOpenChannel(f *testing.F) {
|
func FuzzOpenChannel(f *testing.F) {
|
||||||
f.Fuzz(func(t *testing.T, data []byte) {
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
// We can't use require.Equal for UpfrontShutdownScript, since
|
// We can't use require.Equal for UpfrontShutdownScript, since
|
||||||
|
|||||||
+7
-2
@@ -64,6 +64,7 @@ const (
|
|||||||
MsgReplyChannelRange = 264
|
MsgReplyChannelRange = 264
|
||||||
MsgGossipTimestampRange = 265
|
MsgGossipTimestampRange = 265
|
||||||
MsgChannelAnnouncement2 = 267
|
MsgChannelAnnouncement2 = 267
|
||||||
|
MsgNodeAnnouncement2 = 269
|
||||||
MsgChannelUpdate2 = 271
|
MsgChannelUpdate2 = 271
|
||||||
MsgKickoffSig = 777
|
MsgKickoffSig = 777
|
||||||
|
|
||||||
@@ -166,7 +167,7 @@ func (t MessageType) String() string {
|
|||||||
case MsgChannelUpdate:
|
case MsgChannelUpdate:
|
||||||
return "ChannelUpdate"
|
return "ChannelUpdate"
|
||||||
case MsgNodeAnnouncement:
|
case MsgNodeAnnouncement:
|
||||||
return "NodeAnnouncement"
|
return "NodeAnnouncement1"
|
||||||
case MsgPing:
|
case MsgPing:
|
||||||
return "Ping"
|
return "Ping"
|
||||||
case MsgAnnounceSignatures:
|
case MsgAnnounceSignatures:
|
||||||
@@ -193,6 +194,8 @@ func (t MessageType) String() string {
|
|||||||
return "MsgAnnounceSignatures2"
|
return "MsgAnnounceSignatures2"
|
||||||
case MsgChannelAnnouncement2:
|
case MsgChannelAnnouncement2:
|
||||||
return "ChannelAnnouncement2"
|
return "ChannelAnnouncement2"
|
||||||
|
case MsgNodeAnnouncement2:
|
||||||
|
return "NodeAnnouncement2"
|
||||||
case MsgChannelUpdate2:
|
case MsgChannelUpdate2:
|
||||||
return "ChannelUpdate2"
|
return "ChannelUpdate2"
|
||||||
default:
|
default:
|
||||||
@@ -330,7 +333,7 @@ func makeEmptyMessage(msgType MessageType) (Message, error) {
|
|||||||
case MsgChannelUpdate:
|
case MsgChannelUpdate:
|
||||||
msg = &ChannelUpdate1{}
|
msg = &ChannelUpdate1{}
|
||||||
case MsgNodeAnnouncement:
|
case MsgNodeAnnouncement:
|
||||||
msg = &NodeAnnouncement{}
|
msg = &NodeAnnouncement1{}
|
||||||
case MsgPing:
|
case MsgPing:
|
||||||
msg = &Ping{}
|
msg = &Ping{}
|
||||||
case MsgAnnounceSignatures:
|
case MsgAnnounceSignatures:
|
||||||
@@ -355,6 +358,8 @@ func makeEmptyMessage(msgType MessageType) (Message, error) {
|
|||||||
msg = &AnnounceSignatures2{}
|
msg = &AnnounceSignatures2{}
|
||||||
case MsgChannelAnnouncement2:
|
case MsgChannelAnnouncement2:
|
||||||
msg = &ChannelAnnouncement2{}
|
msg = &ChannelAnnouncement2{}
|
||||||
|
case MsgNodeAnnouncement2:
|
||||||
|
msg = &NodeAnnouncement2{}
|
||||||
case MsgChannelUpdate2:
|
case MsgChannelUpdate2:
|
||||||
msg = &ChannelUpdate2{}
|
msg = &ChannelUpdate2{}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -670,11 +670,11 @@ func newMsgChannelAnnouncement(t testing.TB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newMsgNodeAnnouncement(t testing.TB,
|
func newMsgNodeAnnouncement(t testing.TB,
|
||||||
r *rand.Rand) *lnwire.NodeAnnouncement {
|
r *rand.Rand) *lnwire.NodeAnnouncement1 {
|
||||||
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
msg := &lnwire.NodeAnnouncement{
|
msg := &lnwire.NodeAnnouncement1{
|
||||||
Features: rawFeatureVector(),
|
Features: rawFeatureVector(),
|
||||||
Timestamp: uint32(r.Int31()),
|
Timestamp: uint32(r.Int31()),
|
||||||
Alias: randAlias(r),
|
Alias: randAlias(r),
|
||||||
|
|||||||
+14
-15
@@ -62,11 +62,11 @@ func (n NodeAlias) String() string {
|
|||||||
return string(bytes.Trim(n[:], "\x00"))
|
return string(bytes.Trim(n[:], "\x00"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAnnouncement message is used to announce the presence of a Lightning
|
// NodeAnnouncement1 message is used to announce the presence of a Lightning
|
||||||
// node and also to signal that the node is accepting incoming connections.
|
// node and also to signal that the node is accepting incoming connections.
|
||||||
// Each NodeAnnouncement authenticating the advertised information within the
|
// Each NodeAnnouncement1 authenticating the advertised information within the
|
||||||
// announcement via a signature using the advertised node pubkey.
|
// announcement via a signature using the advertised node pubkey.
|
||||||
type NodeAnnouncement struct {
|
type NodeAnnouncement1 struct {
|
||||||
// Signature is used to prove the ownership of node id.
|
// Signature is used to prove the ownership of node id.
|
||||||
Signature Sig
|
Signature Sig
|
||||||
|
|
||||||
@@ -100,19 +100,19 @@ type NodeAnnouncement struct {
|
|||||||
ExtraOpaqueData ExtraOpaqueData
|
ExtraOpaqueData ExtraOpaqueData
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure NodeAnnouncement implements the
|
// A compile time check to ensure NodeAnnouncement1 implements the
|
||||||
// lnwire.Message interface.
|
// lnwire.Message interface.
|
||||||
var _ Message = (*NodeAnnouncement)(nil)
|
var _ Message = (*NodeAnnouncement1)(nil)
|
||||||
|
|
||||||
// A compile time check to ensure NodeAnnouncement implements the
|
// A compile time check to ensure NodeAnnouncement1 implements the
|
||||||
// lnwire.SizeableMessage interface.
|
// lnwire.SizeableMessage interface.
|
||||||
var _ SizeableMessage = (*NodeAnnouncement)(nil)
|
var _ SizeableMessage = (*NodeAnnouncement1)(nil)
|
||||||
|
|
||||||
// Decode deserializes a serialized NodeAnnouncement stored in the passed
|
// Decode deserializes a serialized NodeAnnouncement1 stored in the passed
|
||||||
// io.Reader observing the specified protocol version.
|
// io.Reader observing the specified protocol version.
|
||||||
//
|
//
|
||||||
// This is part of the lnwire.Message interface.
|
// This is part of the lnwire.Message interface.
|
||||||
func (a *NodeAnnouncement) Decode(r io.Reader, _ uint32) error {
|
func (a *NodeAnnouncement1) Decode(r io.Reader, _ uint32) error {
|
||||||
err := ReadElements(r,
|
err := ReadElements(r,
|
||||||
&a.Signature,
|
&a.Signature,
|
||||||
&a.Features,
|
&a.Features,
|
||||||
@@ -130,11 +130,11 @@ func (a *NodeAnnouncement) Decode(r io.Reader, _ uint32) error {
|
|||||||
return a.ExtraOpaqueData.ValidateTLV()
|
return a.ExtraOpaqueData.ValidateTLV()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode serializes the target NodeAnnouncement into the passed io.Writer
|
// Encode serializes the target NodeAnnouncement1 into the passed io.Writer
|
||||||
// observing the protocol version specified.
|
// observing the protocol version specified.
|
||||||
//
|
//
|
||||||
// This is part of the lnwire.Message interface.
|
// This is part of the lnwire.Message interface.
|
||||||
func (a *NodeAnnouncement) Encode(w *bytes.Buffer, pver uint32) error {
|
func (a *NodeAnnouncement1) Encode(w *bytes.Buffer, pver uint32) error {
|
||||||
if err := WriteSig(w, a.Signature); err != nil {
|
if err := WriteSig(w, a.Signature); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -170,13 +170,12 @@ func (a *NodeAnnouncement) Encode(w *bytes.Buffer, pver uint32) error {
|
|||||||
// wire.
|
// wire.
|
||||||
//
|
//
|
||||||
// This is part of the lnwire.Message interface.
|
// This is part of the lnwire.Message interface.
|
||||||
func (a *NodeAnnouncement) MsgType() MessageType {
|
func (a *NodeAnnouncement1) MsgType() MessageType {
|
||||||
return MsgNodeAnnouncement
|
return MsgNodeAnnouncement
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataToSign returns the part of the message that should be signed.
|
// DataToSign returns the part of the message that should be signed.
|
||||||
func (a *NodeAnnouncement) DataToSign() ([]byte, error) {
|
func (a *NodeAnnouncement1) DataToSign() ([]byte, error) {
|
||||||
|
|
||||||
// We should not include the signatures itself.
|
// We should not include the signatures itself.
|
||||||
buffer := make([]byte, 0, MaxMsgBody)
|
buffer := make([]byte, 0, MaxMsgBody)
|
||||||
buf := bytes.NewBuffer(buffer)
|
buf := bytes.NewBuffer(buffer)
|
||||||
@@ -215,6 +214,6 @@ func (a *NodeAnnouncement) DataToSign() ([]byte, error) {
|
|||||||
// SerializedSize returns the serialized size of the message in bytes.
|
// SerializedSize returns the serialized size of the message in bytes.
|
||||||
//
|
//
|
||||||
// This is part of the lnwire.SizeableMessage interface.
|
// This is part of the lnwire.SizeableMessage interface.
|
||||||
func (a *NodeAnnouncement) SerializedSize() (uint32, error) {
|
func (a *NodeAnnouncement1) SerializedSize() (uint32, error) {
|
||||||
return MessageSerializedSize(a)
|
return MessageSerializedSize(a)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,581 @@
|
|||||||
|
package lnwire
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"image/color"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeAnnouncement2 message is used to announce the presence of a Lightning
|
||||||
|
// node and also to signal that the node is accepting incoming connections.
|
||||||
|
// Each NodeAnnouncement2 authenticating the advertised information within the
|
||||||
|
// announcement via a signature using the advertised node pubkey.
|
||||||
|
type NodeAnnouncement2 struct {
|
||||||
|
// Features is the feature vector that encodes the features supported
|
||||||
|
// by the target node.
|
||||||
|
Features tlv.RecordT[tlv.TlvType0, RawFeatureVector]
|
||||||
|
|
||||||
|
// Color is an optional field used to customize a node's appearance in
|
||||||
|
// maps and graphs.
|
||||||
|
Color tlv.OptionalRecordT[tlv.TlvType1, Color]
|
||||||
|
|
||||||
|
// BlockHeight allows ordering in the case of multiple announcements. We
|
||||||
|
// should ignore the message if block height is not greater than the
|
||||||
|
// last-received. The block height must always be greater or equal to
|
||||||
|
// the block height that the channel funding transaction was confirmed
|
||||||
|
// in.
|
||||||
|
BlockHeight tlv.RecordT[tlv.TlvType2, uint32]
|
||||||
|
|
||||||
|
// Alias is used to customize their node's appearance in maps and
|
||||||
|
// graphs.
|
||||||
|
Alias tlv.OptionalRecordT[tlv.TlvType3, NodeAlias2]
|
||||||
|
|
||||||
|
// NodeID is the public key of the node creating the announcement.
|
||||||
|
NodeID tlv.RecordT[tlv.TlvType4, [33]byte]
|
||||||
|
|
||||||
|
// IPV4Addrs is an optional list of ipv4 addresses that the node is
|
||||||
|
// reachable at.
|
||||||
|
IPV4Addrs tlv.OptionalRecordT[tlv.TlvType5, IPV4Addrs]
|
||||||
|
|
||||||
|
// IPV6Addrs is an optional list of ipv6 addresses that the node is
|
||||||
|
// reachable at.
|
||||||
|
IPV6Addrs tlv.OptionalRecordT[tlv.TlvType7, IPV6Addrs]
|
||||||
|
|
||||||
|
// TorV3Addrs is an optional list of tor v3 addresses that the node is
|
||||||
|
// reachable at.
|
||||||
|
TorV3Addrs tlv.OptionalRecordT[tlv.TlvType9, TorV3Addrs]
|
||||||
|
|
||||||
|
// DNSHostName is an optional DNS hostname that the node is reachable
|
||||||
|
// at.
|
||||||
|
DNSHostName tlv.OptionalRecordT[tlv.TlvType11, DNSAddress]
|
||||||
|
|
||||||
|
// Signature is used to validate the announced data and prove the
|
||||||
|
// ownership of node id.
|
||||||
|
Signature tlv.RecordT[tlv.TlvType160, Sig]
|
||||||
|
|
||||||
|
// Any extra fields in the signed range that we do not yet know about,
|
||||||
|
// but we need to keep them for signature validation and to produce a
|
||||||
|
// valid message.
|
||||||
|
ExtraSignedFields
|
||||||
|
}
|
||||||
|
|
||||||
|
// SerializedSize returns the serialized size of the message in bytes.
|
||||||
|
//
|
||||||
|
// This is part of the lnwire.SizeableMessage interface.
|
||||||
|
func (n *NodeAnnouncement2) SerializedSize() (uint32, error) {
|
||||||
|
return MessageSerializedSize(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllRecords returns all the TLV records for the message. This will include all
|
||||||
|
// the records we know about along with any that we don't know about but that
|
||||||
|
// fall in the signed TLV range.
|
||||||
|
//
|
||||||
|
// NOTE: this is part of the PureTLVMessage interface.
|
||||||
|
func (n *NodeAnnouncement2) AllRecords() []tlv.Record {
|
||||||
|
recordProducers := []tlv.RecordProducer{
|
||||||
|
&n.Features,
|
||||||
|
&n.BlockHeight,
|
||||||
|
&n.NodeID,
|
||||||
|
&n.Signature,
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Color.WhenSome(func(r tlv.RecordT[tlv.TlvType1, Color]) {
|
||||||
|
recordProducers = append(recordProducers, &r)
|
||||||
|
})
|
||||||
|
|
||||||
|
n.Alias.WhenSome(func(a tlv.RecordT[tlv.TlvType3, NodeAlias2]) {
|
||||||
|
recordProducers = append(recordProducers, &a)
|
||||||
|
})
|
||||||
|
|
||||||
|
n.IPV4Addrs.WhenSome(func(r tlv.RecordT[tlv.TlvType5, IPV4Addrs]) {
|
||||||
|
recordProducers = append(recordProducers, &r)
|
||||||
|
})
|
||||||
|
|
||||||
|
n.IPV6Addrs.WhenSome(func(r tlv.RecordT[tlv.TlvType7, IPV6Addrs]) {
|
||||||
|
recordProducers = append(recordProducers, &r)
|
||||||
|
})
|
||||||
|
|
||||||
|
n.TorV3Addrs.WhenSome(func(r tlv.RecordT[tlv.TlvType9, TorV3Addrs]) {
|
||||||
|
recordProducers = append(recordProducers, &r)
|
||||||
|
})
|
||||||
|
|
||||||
|
n.DNSHostName.WhenSome(func(r tlv.RecordT[tlv.TlvType11, DNSAddress]) {
|
||||||
|
recordProducers = append(recordProducers, &r)
|
||||||
|
})
|
||||||
|
|
||||||
|
recordProducers = append(recordProducers, RecordsAsProducers(
|
||||||
|
tlv.MapToRecords(n.ExtraSignedFields),
|
||||||
|
)...)
|
||||||
|
|
||||||
|
return ProduceRecordsSorted(recordProducers...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode deserializes a serialized NodeAnnouncement2 stored in the passed
|
||||||
|
// io.Reader observing the specified protocol version.
|
||||||
|
//
|
||||||
|
// This is part of the lnwire.Message interface.
|
||||||
|
func (n *NodeAnnouncement2) Decode(r io.Reader, _ uint32) error {
|
||||||
|
var (
|
||||||
|
color = tlv.ZeroRecordT[tlv.TlvType1, Color]()
|
||||||
|
alias = tlv.ZeroRecordT[tlv.TlvType3, NodeAlias2]()
|
||||||
|
ipv4 = tlv.ZeroRecordT[tlv.TlvType5, IPV4Addrs]()
|
||||||
|
ipv6 = tlv.ZeroRecordT[tlv.TlvType7, IPV6Addrs]()
|
||||||
|
torV3 = tlv.ZeroRecordT[tlv.TlvType9, TorV3Addrs]()
|
||||||
|
dns = tlv.ZeroRecordT[tlv.TlvType11, DNSAddress]()
|
||||||
|
)
|
||||||
|
|
||||||
|
stream, err := tlv.NewStream(ProduceRecordsSorted(
|
||||||
|
&n.Features,
|
||||||
|
&n.BlockHeight,
|
||||||
|
&n.NodeID,
|
||||||
|
&n.Signature,
|
||||||
|
&alias,
|
||||||
|
&color,
|
||||||
|
&ipv4,
|
||||||
|
&ipv6,
|
||||||
|
&torV3,
|
||||||
|
&dns,
|
||||||
|
)...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
n.Signature.Val.ForceSchnorr()
|
||||||
|
|
||||||
|
typeMap, err := stream.DecodeWithParsedTypesP2P(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := typeMap[n.Alias.TlvType()]; ok {
|
||||||
|
n.Alias = tlv.SomeRecordT(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := typeMap[n.Color.TlvType()]; ok {
|
||||||
|
n.Color = tlv.SomeRecordT(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := typeMap[n.IPV4Addrs.TlvType()]; ok {
|
||||||
|
n.IPV4Addrs = tlv.SomeRecordT(ipv4)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := typeMap[n.IPV6Addrs.TlvType()]; ok {
|
||||||
|
n.IPV6Addrs = tlv.SomeRecordT(ipv6)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := typeMap[n.TorV3Addrs.TlvType()]; ok {
|
||||||
|
n.TorV3Addrs = tlv.SomeRecordT(torV3)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := typeMap[n.DNSHostName.TlvType()]; ok {
|
||||||
|
n.DNSHostName = tlv.SomeRecordT(dns)
|
||||||
|
}
|
||||||
|
|
||||||
|
n.ExtraSignedFields = ExtraSignedFieldsFromTypeMap(typeMap)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode serializes the target NodeAnnouncement2 into the passed io.Writer
|
||||||
|
// observing the protocol version specified.
|
||||||
|
//
|
||||||
|
// This is part of the lnwire.Message interface.
|
||||||
|
func (n *NodeAnnouncement2) Encode(w *bytes.Buffer, _ uint32) error {
|
||||||
|
return EncodePureTLVMessage(n, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgType returns the integer uniquely identifying this message type on the
|
||||||
|
// wire.
|
||||||
|
//
|
||||||
|
// This is part of the lnwire.Message interface.
|
||||||
|
func (n *NodeAnnouncement2) MsgType() MessageType {
|
||||||
|
return MsgNodeAnnouncement2
|
||||||
|
}
|
||||||
|
|
||||||
|
// A compile-time check to ensure NodeAnnouncement2 implements the Message
|
||||||
|
// interface.
|
||||||
|
var _ Message = (*NodeAnnouncement2)(nil)
|
||||||
|
|
||||||
|
// A compile-time check to ensure NodeAnnouncement2 implements the
|
||||||
|
// PureTLVMessage interface.
|
||||||
|
var _ PureTLVMessage = (*NodeAnnouncement2)(nil)
|
||||||
|
|
||||||
|
// A compile time check to ensure ChannelAnnouncement2 implements the
|
||||||
|
// lnwire.SizeableMessage interface.
|
||||||
|
var _ SizeableMessage = (*NodeAnnouncement2)(nil)
|
||||||
|
|
||||||
|
// NodeAlias2 represents a UTF-8 encoded node alias with a maximum length of 32
|
||||||
|
// bytes.
|
||||||
|
type NodeAlias2 []byte
|
||||||
|
|
||||||
|
// Record returns a TLV record for encoding/decoding NodeAlias2.
|
||||||
|
func (n *NodeAlias2) Record() tlv.Record {
|
||||||
|
sizeFunc := func() uint64 {
|
||||||
|
return uint64(len(*n))
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.MakeDynamicRecord(
|
||||||
|
0, n, sizeFunc, nodeAlias2Encoder, nodeAlias2Decoder,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateNodeAlias2 validates that the node alias is valid UTF-8 and within
|
||||||
|
// the 32-byte limit.
|
||||||
|
func ValidateNodeAlias2(alias []byte) error {
|
||||||
|
if len(alias) == 0 {
|
||||||
|
return errors.New("node alias cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(alias) > 32 {
|
||||||
|
return fmt.Errorf("node alias exceeds 32 bytes: length %d",
|
||||||
|
len(alias))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !utf8.Valid(alias) {
|
||||||
|
return errors.New("node alias contains invalid UTF-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodeAlias2Encoder encodes a NodeAlias2 as raw UTF-8 bytes.
|
||||||
|
func nodeAlias2Encoder(w io.Writer, val any, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*NodeAlias2); ok {
|
||||||
|
if err := ValidateNodeAlias2(*v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := w.Write(*v)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "NodeAlias2")
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodeAlias2Decoder decodes raw bytes into a NodeAlias2.
|
||||||
|
func nodeAlias2Decoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
|
||||||
|
if v, ok := val.(*NodeAlias2); ok {
|
||||||
|
if l > 32 {
|
||||||
|
return fmt.Errorf("node alias exceeds 32 bytes: %d", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
aliasBytes := make([]byte, l)
|
||||||
|
if _, err := io.ReadFull(r, aliasBytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ValidateNodeAlias2(aliasBytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*v = aliasBytes
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForDecodingErr(val, "NodeAlias2", l, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color is a custom type to represent a color.RGBA that can be encoded/decoded
|
||||||
|
// as a TLV record.
|
||||||
|
type Color color.RGBA
|
||||||
|
|
||||||
|
// Record returns a TLV record for encoding/decoding Color.
|
||||||
|
func (c *Color) Record() tlv.Record {
|
||||||
|
return tlv.MakeStaticRecord(0, c, 3, rgbEncoder, rgbDecoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rgbEncoder encodes a Color as RGB bytes.
|
||||||
|
func rgbEncoder(w io.Writer, val any, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*Color); ok {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
err := WriteColorRGBA(buf, color.RGBA(*v))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = w.Write(buf.Bytes())
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "Color")
|
||||||
|
}
|
||||||
|
|
||||||
|
// rgbDecoder decodes RGB bytes into a Color.
|
||||||
|
func rgbDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
|
||||||
|
if v, ok := val.(*Color); ok {
|
||||||
|
return ReadElements(r, &v.R, &v.G, &v.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForDecodingErr(val, "Color", l, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipv4AddrEncodedSize is the number of bytes required to encode a single ipv4
|
||||||
|
// address. Four bytes are used to encode the IP address and two bytes for the
|
||||||
|
// port number.
|
||||||
|
const ipv4AddrEncodedSize = 4 + 2
|
||||||
|
|
||||||
|
// IPV4Addrs is a list of ipv4 addresses that can be encoded as a TLV record.
|
||||||
|
type IPV4Addrs []*net.TCPAddr
|
||||||
|
|
||||||
|
// Record returns a Record that can be used to encode/decode a IPV4Addrs
|
||||||
|
// to/from a TLV stream.
|
||||||
|
func (a *IPV4Addrs) Record() tlv.Record {
|
||||||
|
return tlv.MakeDynamicRecord(
|
||||||
|
0, a, a.encodedSize, ipv4AddrsEncoder, ipv4AddrsDecoder,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodedSize returns the number of bytes required to encode an IPV4Addrs
|
||||||
|
// variable.
|
||||||
|
func (a *IPV4Addrs) encodedSize() uint64 {
|
||||||
|
return uint64(len(*a) * ipv4AddrEncodedSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipv4AddrsEncoder encodes IPv4 addresses as TLV bytes.
|
||||||
|
func ipv4AddrsEncoder(w io.Writer, val interface{}, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*IPV4Addrs); ok {
|
||||||
|
for _, ip := range *v {
|
||||||
|
_, err := w.Write(ip.IP.To4())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var port [2]byte
|
||||||
|
binary.BigEndian.PutUint16(port[:], uint16(ip.Port))
|
||||||
|
_, err = w.Write(port[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.IPV4Addrs")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipv4AddrsDecoder decodes TLV bytes into IPv4 addresses.
|
||||||
|
func ipv4AddrsDecoder(r io.Reader, val interface{}, _ *[8]byte,
|
||||||
|
l uint64) error {
|
||||||
|
|
||||||
|
if v, ok := val.(*IPV4Addrs); ok {
|
||||||
|
if l%(ipv4AddrEncodedSize) != 0 {
|
||||||
|
return fmt.Errorf("invalid ipv4 list encoding")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
numAddrs = int(l / ipv4AddrEncodedSize)
|
||||||
|
addrs = make([]*net.TCPAddr, 0, numAddrs)
|
||||||
|
ip [4]byte
|
||||||
|
port [2]byte
|
||||||
|
)
|
||||||
|
for len(addrs) < numAddrs {
|
||||||
|
_, err := r.Read(ip[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = r.Read(port[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addrs = append(addrs, &net.TCPAddr{
|
||||||
|
IP: ip[:],
|
||||||
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*v = addrs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.IPV4Addrs")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPV6Addrs is a list of ipv6 addresses that can be encoded as a TLV record.
|
||||||
|
type IPV6Addrs []*net.TCPAddr
|
||||||
|
|
||||||
|
// Record returns a Record that can be used to encode/decode a IPV4Addrs
|
||||||
|
// to/from a TLV stream.
|
||||||
|
func (a *IPV6Addrs) Record() tlv.Record {
|
||||||
|
return tlv.MakeDynamicRecord(
|
||||||
|
0, a, a.encodedSize, ipv6AddrsEncoder, ipv6AddrsDecoder,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipv6AddrEncodedSize is the number of bytes required to encode a single ipv6
|
||||||
|
// address. Sixteen bytes are used to encode the IP address and two bytes for
|
||||||
|
// the port number.
|
||||||
|
const ipv6AddrEncodedSize = 16 + 2
|
||||||
|
|
||||||
|
// encodedSize returns the number of bytes required to encode an IPV6Addrs
|
||||||
|
// variable.
|
||||||
|
func (a *IPV6Addrs) encodedSize() uint64 {
|
||||||
|
return uint64(len(*a) * ipv6AddrEncodedSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipv6AddrsEncoder encodes IPv6 addresses as TLV bytes.
|
||||||
|
func ipv6AddrsEncoder(w io.Writer, val interface{}, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*IPV6Addrs); ok {
|
||||||
|
for _, ip := range *v {
|
||||||
|
_, err := w.Write(ip.IP.To16())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var port [2]byte
|
||||||
|
binary.BigEndian.PutUint16(port[:], uint16(ip.Port))
|
||||||
|
_, err = w.Write(port[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.IPV6Addrs")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipv6AddrsDecoder decodes TLV bytes into IPv6 addresses.
|
||||||
|
func ipv6AddrsDecoder(r io.Reader, val interface{}, _ *[8]byte,
|
||||||
|
l uint64) error {
|
||||||
|
|
||||||
|
if v, ok := val.(*IPV6Addrs); ok {
|
||||||
|
if l%(ipv6AddrEncodedSize) != 0 {
|
||||||
|
return fmt.Errorf("invalid ipv6 list encoding")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
numAddrs = int(l / ipv6AddrEncodedSize)
|
||||||
|
addrs = make([]*net.TCPAddr, 0, numAddrs)
|
||||||
|
ip [16]byte
|
||||||
|
port [2]byte
|
||||||
|
)
|
||||||
|
for len(addrs) < numAddrs {
|
||||||
|
_, err := r.Read(ip[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = r.Read(port[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addrs = append(addrs, &net.TCPAddr{
|
||||||
|
IP: ip[:],
|
||||||
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*v = addrs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.IPV6Addrs")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TorV3Addrs is a list of tor v3 addresses that can be encoded as a TLV record.
|
||||||
|
type TorV3Addrs []*tor.OnionAddr
|
||||||
|
|
||||||
|
// torV3AddrEncodedSize is the number of bytes required to encode a single tor
|
||||||
|
// v3 address.
|
||||||
|
const torV3AddrEncodedSize = tor.V3DecodedLen + 2
|
||||||
|
|
||||||
|
// encodedSize returns the number of bytes required to encode an TorV3Addrs
|
||||||
|
// variable.
|
||||||
|
func (a *TorV3Addrs) encodedSize() uint64 {
|
||||||
|
return uint64(len(*a) * torV3AddrEncodedSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record returns a Record that can be used to encode/decode a IPV4Addrs
|
||||||
|
// to/from a TLV stream.
|
||||||
|
func (a *TorV3Addrs) Record() tlv.Record {
|
||||||
|
return tlv.MakeDynamicRecord(
|
||||||
|
0, a, a.encodedSize, torV3AddrsEncoder, torV3AddrsDecoder,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// torV3AddrsEncoder encodes Tor v3 addresses as TLV bytes.
|
||||||
|
func torV3AddrsEncoder(w io.Writer, val interface{}, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*TorV3Addrs); ok {
|
||||||
|
for _, addr := range *v {
|
||||||
|
encodedHostLen := tor.V3Len - tor.OnionSuffixLen
|
||||||
|
host, err := tor.Base32Encoding.DecodeString(
|
||||||
|
addr.OnionService[:encodedHostLen],
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(host) != tor.V3DecodedLen {
|
||||||
|
return fmt.Errorf("expected a tor v3 host "+
|
||||||
|
"length of %d, got: %d",
|
||||||
|
tor.V3DecodedLen, len(host))
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = w.Write(host); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
binary.BigEndian.PutUint16(port[:], uint16(addr.Port))
|
||||||
|
if _, err = w.Write(port[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.TorV3Addrs")
|
||||||
|
}
|
||||||
|
|
||||||
|
// torV3AddrsDecoder decodes TLV bytes into Tor v3 addresses.
|
||||||
|
func torV3AddrsDecoder(r io.Reader, val interface{}, _ *[8]byte,
|
||||||
|
l uint64) error {
|
||||||
|
|
||||||
|
if v, ok := val.(*TorV3Addrs); ok {
|
||||||
|
if l%torV3AddrEncodedSize != 0 {
|
||||||
|
return fmt.Errorf("invalid tor v3 list encoding")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
numAddrs = int(l / torV3AddrEncodedSize)
|
||||||
|
addrs = make([]*tor.OnionAddr, 0, numAddrs)
|
||||||
|
ip [tor.V3DecodedLen]byte
|
||||||
|
p [2]byte
|
||||||
|
)
|
||||||
|
for len(addrs) < numAddrs {
|
||||||
|
_, err := r.Read(ip[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = r.Read(p[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
onionService := tor.Base32Encoding.EncodeToString(ip[:])
|
||||||
|
onionService += tor.OnionSuffix
|
||||||
|
|
||||||
|
if len(onionService) != tor.V3Len {
|
||||||
|
return fmt.Errorf("expected a tor v3 onion "+
|
||||||
|
"service length of %d, got: %d",
|
||||||
|
tor.V3Len, len(onionService))
|
||||||
|
}
|
||||||
|
|
||||||
|
port := int(binary.BigEndian.Uint16(p[:]))
|
||||||
|
addrs = append(addrs, &tor.OnionAddr{
|
||||||
|
OnionService: onionService,
|
||||||
|
Port: port,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*v = addrs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "lnwire.TorV3Addrs")
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package lnwire
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestNodeAnn2EncodeDecode tests the encoding and decoding of the
|
||||||
|
// NodeAnnouncement2 message using hardcoded byte slices.
|
||||||
|
func TestNodeAnn2EncodeDecode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// We'll create a raw byte stream that represents a valid
|
||||||
|
// NodeAnnouncement2 message with various known and unknown fields in
|
||||||
|
// the signed TLV ranges along with the signature in the unsigned range.
|
||||||
|
rawBytes := []byte{
|
||||||
|
// Features record.
|
||||||
|
0x00, // type.
|
||||||
|
0x02, // length.
|
||||||
|
0x1, 0x2, // value.
|
||||||
|
|
||||||
|
// Color record (optional).
|
||||||
|
0x01, // type.
|
||||||
|
0x03, // length.
|
||||||
|
0xff, 0x00, 0x80, // value: RGB(255, 0, 128).
|
||||||
|
|
||||||
|
// BlockHeight record.
|
||||||
|
0x02, // type.
|
||||||
|
0x04, // length.
|
||||||
|
0x00, 0x01, 0x86, 0xa0, // value: 100000.
|
||||||
|
|
||||||
|
// Alias record (optional).
|
||||||
|
0x03, // type.
|
||||||
|
0x20, // length (32).
|
||||||
|
0x4c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e,
|
||||||
|
0x67, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x54,
|
||||||
|
0x65, 0x73, 0x74, 0x20, 0x41, 0x6c, 0x69, 0x61,
|
||||||
|
0x73, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x21, 0x00, // value.
|
||||||
|
|
||||||
|
// NodeID record.
|
||||||
|
0x04, // type.
|
||||||
|
0x21, // length.
|
||||||
|
0x02, 0x28, 0xf2, 0xaf, 0xa, 0xbe, 0x32, 0x24, 0x3, 0x48, 0xf,
|
||||||
|
0xb3, 0xee, 0x17, 0x2f, 0x7f, 0x16, 0x1, 0xe6, 0x7d, 0x1d, 0xa6,
|
||||||
|
0xca, 0xd4, 0xb, 0x54, 0xc4, 0x46, 0x8d, 0x48, 0x23, 0x6c, 0x39,
|
||||||
|
|
||||||
|
// IPV4Addrs record (optional).
|
||||||
|
0x05, // type.
|
||||||
|
0x0c, // length (12 bytes).
|
||||||
|
0x0a, 0x00, 0x00, 0x01, 0x23, 0x28, // 10.0.0.1:9000
|
||||||
|
0x0a, 0x00, 0x00, 0x01, 0x1f, 0x90, // 10.0.0.1:8080
|
||||||
|
|
||||||
|
// IPV6Addrs record (optional).
|
||||||
|
0x07, // type.
|
||||||
|
0x12, // length.
|
||||||
|
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, // IPv6 address
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 2001:db8::1
|
||||||
|
0x1f, 0x40, // port 8000
|
||||||
|
|
||||||
|
// TorV3Addrs record (optional).
|
||||||
|
0x09, // type.
|
||||||
|
0x25, // length (37 bytes = 1 address).
|
||||||
|
// value: 35-byte tor v3 address + 2-byte port.
|
||||||
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||||
|
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||||
|
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||||
|
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
0x21, 0x22, 0x23,
|
||||||
|
0x23, 0x28, // port 9000.
|
||||||
|
|
||||||
|
// DNSHostName record (optional).
|
||||||
|
0x0b, // type (11).
|
||||||
|
0x17, // length (23).
|
||||||
|
0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e,
|
||||||
|
0x67, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, // value.
|
||||||
|
0x65, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
|
0x23, 0x28, // port 9000.
|
||||||
|
|
||||||
|
// Signature.
|
||||||
|
0xa0, // type.
|
||||||
|
0x40, // length.
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb,
|
||||||
|
0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||||
|
0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
|
||||||
|
0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
|
||||||
|
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
|
||||||
|
0x3f, // value.
|
||||||
|
}
|
||||||
|
secondSignedRangeType := new(bytes.Buffer)
|
||||||
|
var buf [8]byte
|
||||||
|
err := tlv.WriteVarInt(
|
||||||
|
secondSignedRangeType, pureTLVSignedSecondRangeStart+1, &buf,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
rawBytes = append(rawBytes, secondSignedRangeType.Bytes()...) // type.
|
||||||
|
rawBytes = append(rawBytes, []byte{
|
||||||
|
0x02, // length.
|
||||||
|
0x79, 0x79, // value.
|
||||||
|
}...)
|
||||||
|
|
||||||
|
// Now, create a new empty message and decode the raw bytes into it.
|
||||||
|
msg := &NodeAnnouncement2{}
|
||||||
|
r := bytes.NewReader(rawBytes)
|
||||||
|
err = msg.Decode(r, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Next, encode the message back into a new byte buffer.
|
||||||
|
var b bytes.Buffer
|
||||||
|
err = msg.Encode(&b, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// The re-encoded bytes should be exactly the same as the original raw
|
||||||
|
// bytes.
|
||||||
|
require.Equal(t, rawBytes, b.Bytes())
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package lnwire
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OutPoint describes an outpoint of a transaction via its transaction hash
|
||||||
|
// and the outpoint index. This is a thin wrapper around the wire.OutPoint to
|
||||||
|
// provide TLV encoding/decoding.
|
||||||
|
type OutPoint wire.OutPoint
|
||||||
|
|
||||||
|
// Record returns a TLV record that can be used to encode/decode the OutPoint.
|
||||||
|
//
|
||||||
|
// NOTE: this is part of the tlv.RecordProducer interface.
|
||||||
|
func (o *OutPoint) Record() tlv.Record {
|
||||||
|
return tlv.MakeStaticRecord(0, o, 34, outpointEncoder, outpointDecoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// outpointEncoder is a TLV encoder for OutPoint.
|
||||||
|
func outpointEncoder(w io.Writer, val any, _ *[8]byte) error {
|
||||||
|
if v, ok := val.(*OutPoint); ok {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
err := WriteOutPoint(buf, wire.OutPoint(*v))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = w.Write(buf.Bytes())
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForEncodingErr(val, "OutPoint")
|
||||||
|
}
|
||||||
|
|
||||||
|
// outpointDecoder is a TLV decoder for OutPoint.
|
||||||
|
func outpointDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
|
||||||
|
if v, ok := val.(*OutPoint); ok {
|
||||||
|
var o wire.OutPoint
|
||||||
|
if err := ReadElement(r, &o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*v = OutPoint(o)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlv.NewTypeForDecodingErr(val, "OutPoint", l, 34)
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package lnwire
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"pgregory.net/rapid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestOutPointTLVEncoding tests the TLV encoding and decoding of OutPoint
|
||||||
|
// structs using the Record interface.
|
||||||
|
func TestOutPointTLVEncoding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testOutPoint := OutPoint(wire.OutPoint{
|
||||||
|
Hash: chainhash.Hash{
|
||||||
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||||
|
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||||
|
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||||
|
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
},
|
||||||
|
Index: 12345,
|
||||||
|
})
|
||||||
|
|
||||||
|
var extraData ExtraOpaqueData
|
||||||
|
require.NoError(t, extraData.PackRecords(&testOutPoint))
|
||||||
|
|
||||||
|
var decodedOutPoint OutPoint
|
||||||
|
tlvs, err := extraData.ExtractRecords(&decodedOutPoint)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Contains(t, tlvs, tlv.Type(0))
|
||||||
|
require.Equal(t, testOutPoint, decodedOutPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestOutPointRecord tests the TLV Record interface of OutPoint
|
||||||
|
// by directly encoding and decoding using the Record method.
|
||||||
|
func TestOutPointRecord(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testOutPoint := OutPoint(wire.OutPoint{
|
||||||
|
Hash: chainhash.Hash{
|
||||||
|
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
|
||||||
|
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
|
||||||
|
0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
|
||||||
|
0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
|
||||||
|
},
|
||||||
|
Index: 65535,
|
||||||
|
})
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
record := testOutPoint.Record()
|
||||||
|
require.NoError(t, record.Encode(&buf))
|
||||||
|
|
||||||
|
var decodedOutPoint OutPoint
|
||||||
|
decodedRecord := decodedOutPoint.Record()
|
||||||
|
require.NoError(t, decodedRecord.Decode(&buf, uint64(buf.Len())))
|
||||||
|
|
||||||
|
require.Equal(t, testOutPoint, decodedOutPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestOutPointProperty uses property-based testing to verify that OutPoint
|
||||||
|
// TLV encoding and decoding is correct for random OutPoint values.
|
||||||
|
func TestOutPointProperty(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
scenario := func(t *rapid.T) {
|
||||||
|
wireOutPoint := RandOutPoint(t)
|
||||||
|
lnOutPoint := OutPoint(wireOutPoint)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
record := lnOutPoint.Record()
|
||||||
|
err := record.Encode(&buf)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var decodedOutPoint OutPoint
|
||||||
|
decodedRecord := decodedOutPoint.Record()
|
||||||
|
err = decodedRecord.Decode(&buf, uint64(buf.Len()))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, lnOutPoint, decodedOutPoint)
|
||||||
|
require.Equal(t, wireOutPoint, wire.OutPoint(decodedOutPoint))
|
||||||
|
}
|
||||||
|
|
||||||
|
rapid.Check(t, scenario)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestOutPointZeroValues tests that OutPoint handles zero values correctly.
|
||||||
|
func TestOutPointZeroValues(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
zeroOutPoint := OutPoint(wire.OutPoint{})
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
record := zeroOutPoint.Record()
|
||||||
|
require.NoError(t, record.Encode(&buf))
|
||||||
|
|
||||||
|
var decodedOutPoint OutPoint
|
||||||
|
decodedRecord := decodedOutPoint.Record()
|
||||||
|
require.NoError(t, decodedRecord.Decode(&buf, uint64(buf.Len())))
|
||||||
|
|
||||||
|
require.Equal(t, zeroOutPoint, decodedOutPoint)
|
||||||
|
}
|
||||||
+172
-4
@@ -5,12 +5,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/lightningnetwork/lnd/fn/v2"
|
"github.com/lightningnetwork/lnd/fn/v2"
|
||||||
"github.com/lightningnetwork/lnd/tlv"
|
"github.com/lightningnetwork/lnd/tlv"
|
||||||
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"pgregory.net/rapid"
|
"pgregory.net/rapid"
|
||||||
)
|
)
|
||||||
@@ -291,6 +293,10 @@ func (c *ChannelAnnouncement2) RandTestMessage(t *rapid.T) Message {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg.Outpoint = tlv.NewRecordT[tlv.TlvType18, OutPoint](
|
||||||
|
OutPoint(RandOutPoint(t)),
|
||||||
|
)
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,6 +571,18 @@ func (c *ChannelUpdate2) RandTestMessage(t *rapid.T) Message {
|
|||||||
ExtraSignedFields: make(map[uint64][]byte),
|
ExtraSignedFields: make(map[uint64][]byte),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rapid.Bool().Draw(t, "includeInboundFee") {
|
||||||
|
base := rapid.IntRange(-1000, 1000).Draw(t, "inFeeBase")
|
||||||
|
rate := rapid.IntRange(-1000, 1000).Draw(t, "inFeeProp")
|
||||||
|
fee := Fee{
|
||||||
|
BaseFee: int32(base),
|
||||||
|
FeeRate: int32(rate),
|
||||||
|
}
|
||||||
|
msg.InboundFee = tlv.SomeRecordT(
|
||||||
|
tlv.NewRecordT[tlv.TlvType55555](fee),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
msg.Signature.Val = RandSignature(t)
|
msg.Signature.Val = RandSignature(t)
|
||||||
msg.Signature.Val.ForceSchnorr()
|
msg.Signature.Val.ForceSchnorr()
|
||||||
|
|
||||||
@@ -1211,15 +1229,19 @@ func (ks *KickoffSig) RandTestMessage(t *rapid.T) Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure NodeAnnouncement implements the
|
// A compile time check to ensure NodeAnnouncement1 implements the
|
||||||
// lnwire.TestMessage interface.
|
// lnwire.TestMessage interface.
|
||||||
var _ TestMessage = (*NodeAnnouncement)(nil)
|
var _ TestMessage = (*NodeAnnouncement1)(nil)
|
||||||
|
|
||||||
|
// A compile time check to ensure NodeAnnouncement2 implements the
|
||||||
|
// lnwire.TestMessage interface.
|
||||||
|
var _ TestMessage = (*NodeAnnouncement2)(nil)
|
||||||
|
|
||||||
// RandTestMessage populates the message with random data suitable for testing.
|
// RandTestMessage populates the message with random data suitable for testing.
|
||||||
// It uses the rapid testing framework to generate random values.
|
// It uses the rapid testing framework to generate random values.
|
||||||
//
|
//
|
||||||
// This is part of the TestMessage interface.
|
// This is part of the TestMessage interface.
|
||||||
func (a *NodeAnnouncement) RandTestMessage(t *rapid.T) Message {
|
func (a *NodeAnnouncement1) RandTestMessage(t *rapid.T) Message {
|
||||||
// Generate random compressed public key for node ID
|
// Generate random compressed public key for node ID
|
||||||
pubKey := RandPubKey(t)
|
pubKey := RandPubKey(t)
|
||||||
var nodeID [33]byte
|
var nodeID [33]byte
|
||||||
@@ -1232,7 +1254,7 @@ func (a *NodeAnnouncement) RandTestMessage(t *rapid.T) Message {
|
|||||||
B: uint8(rapid.IntRange(0, 255).Draw(t, "rgbB")),
|
B: uint8(rapid.IntRange(0, 255).Draw(t, "rgbB")),
|
||||||
}
|
}
|
||||||
|
|
||||||
return &NodeAnnouncement{
|
return &NodeAnnouncement1{
|
||||||
Signature: RandSignature(t),
|
Signature: RandSignature(t),
|
||||||
Features: RandFeatureVector(t),
|
Features: RandFeatureVector(t),
|
||||||
Timestamp: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
|
Timestamp: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
|
||||||
@@ -1246,6 +1268,131 @@ func (a *NodeAnnouncement) RandTestMessage(t *rapid.T) Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandTestMessage populates the message with random data suitable for testing.
|
||||||
|
// It uses the rapid testing framework to generate random values.
|
||||||
|
//
|
||||||
|
// This is part of the TestMessage interface.
|
||||||
|
func (n *NodeAnnouncement2) RandTestMessage(t *rapid.T) Message {
|
||||||
|
features := RandFeatureVector(t)
|
||||||
|
blockHeight := uint32(rapid.IntRange(0, 1000000).Draw(t, "blockHeight"))
|
||||||
|
|
||||||
|
// Generate random compressed public key for node ID
|
||||||
|
pubKey := RandPubKey(t)
|
||||||
|
var nodeID [33]byte
|
||||||
|
copy(nodeID[:], pubKey.SerializeCompressed())
|
||||||
|
|
||||||
|
msg := &NodeAnnouncement2{
|
||||||
|
Features: tlv.NewRecordT[tlv.TlvType0](*features),
|
||||||
|
BlockHeight: tlv.NewPrimitiveRecord[tlv.TlvType2](
|
||||||
|
blockHeight,
|
||||||
|
),
|
||||||
|
NodeID: tlv.NewPrimitiveRecord[tlv.TlvType4](nodeID),
|
||||||
|
ExtraSignedFields: make(map[uint64][]byte),
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Signature.Val = RandSignature(t)
|
||||||
|
msg.Signature.Val.ForceSchnorr()
|
||||||
|
|
||||||
|
// Test optional fields one by one
|
||||||
|
if rapid.Bool().Draw(t, "includeColor") {
|
||||||
|
rgbColor := Color{
|
||||||
|
R: uint8(rapid.IntRange(0, 255).Draw(t, "rgbR")),
|
||||||
|
G: uint8(rapid.IntRange(0, 255).Draw(t, "rgbG")),
|
||||||
|
B: uint8(rapid.IntRange(0, 255).Draw(t, "rgbB")),
|
||||||
|
}
|
||||||
|
colorRecord := tlv.ZeroRecordT[tlv.TlvType1, Color]()
|
||||||
|
colorRecord.Val = rgbColor
|
||||||
|
msg.Color = tlv.SomeRecordT(colorRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rapid.Bool().Draw(t, "includeAlias") {
|
||||||
|
aliasBytes := RandNodeAlias2(t)
|
||||||
|
aliasRecord := tlv.ZeroRecordT[tlv.TlvType3, NodeAlias2]()
|
||||||
|
aliasRecord.Val = aliasBytes
|
||||||
|
msg.Alias = tlv.SomeRecordT(aliasRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rapid.Bool().Draw(t, "includeIPV4Addrs") {
|
||||||
|
ipv4Addrs := make(IPV4Addrs, 1)
|
||||||
|
ip := make(net.IP, 4)
|
||||||
|
ip[0] = uint8(rapid.IntRange(1, 223).Draw(t, "ip4_0"))
|
||||||
|
ip[1] = uint8(rapid.IntRange(0, 255).Draw(t, "ip4_1"))
|
||||||
|
ip[2] = uint8(rapid.IntRange(0, 255).Draw(t, "ip4_2"))
|
||||||
|
ip[3] = uint8(rapid.IntRange(1, 254).Draw(t, "ip4_3"))
|
||||||
|
|
||||||
|
ipv4Addrs[0] = &net.TCPAddr{
|
||||||
|
IP: ip,
|
||||||
|
Port: rapid.IntRange(1, 65535).Draw(t, "port4"),
|
||||||
|
}
|
||||||
|
|
||||||
|
ipv4Record := tlv.ZeroRecordT[tlv.TlvType5, IPV4Addrs]()
|
||||||
|
ipv4Record.Val = ipv4Addrs
|
||||||
|
msg.IPV4Addrs = tlv.SomeRecordT(ipv4Record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rapid.Bool().Draw(t, "includeIPV6Addrs") {
|
||||||
|
ipv6Addrs := make(IPV6Addrs, 1)
|
||||||
|
ip := make(net.IP, 16)
|
||||||
|
// Generate random IPv6 address.
|
||||||
|
for j := 0; j < 16; j++ {
|
||||||
|
ip[j] = uint8(rapid.IntRange(0, 255).Draw(
|
||||||
|
t, fmt.Sprintf("ip6_%d", j)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipv6Addrs[0] = &net.TCPAddr{
|
||||||
|
IP: ip,
|
||||||
|
Port: rapid.IntRange(1, 65535).Draw(t, "port6"),
|
||||||
|
}
|
||||||
|
|
||||||
|
ipv6Record := tlv.ZeroRecordT[tlv.TlvType7, IPV6Addrs]()
|
||||||
|
ipv6Record.Val = ipv6Addrs
|
||||||
|
msg.IPV6Addrs = tlv.SomeRecordT(ipv6Record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rapid.Bool().Draw(t, "includeTorV3Addrs") {
|
||||||
|
torV3Addrs := make(TorV3Addrs, 1)
|
||||||
|
onionBytes := rapid.SliceOfN(rapid.Byte(), 35, 35).Draw(
|
||||||
|
t, "onion",
|
||||||
|
)
|
||||||
|
onionService := tor.Base32Encoding.EncodeToString(onionBytes) +
|
||||||
|
tor.OnionSuffix
|
||||||
|
|
||||||
|
torV3Addrs[0] = &tor.OnionAddr{
|
||||||
|
OnionService: onionService,
|
||||||
|
Port: rapid.IntRange(1, 65535).Draw(
|
||||||
|
t, "torPort",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
torV3Record := tlv.ZeroRecordT[tlv.TlvType9, TorV3Addrs]()
|
||||||
|
torV3Record.Val = torV3Addrs
|
||||||
|
msg.TorV3Addrs = tlv.SomeRecordT(torV3Record)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rapid.Bool().Draw(t, "includeDNSHostName") {
|
||||||
|
// Generate a valid DNS hostname.
|
||||||
|
hostname := genValidHostname(t)
|
||||||
|
port := rapid.Uint16Range(1, 65535).Draw(t, "dnsPort")
|
||||||
|
|
||||||
|
dnsAddr := DNSAddress{
|
||||||
|
Hostname: hostname,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsRecord := tlv.ZeroRecordT[tlv.TlvType11, DNSAddress]()
|
||||||
|
dnsRecord.Val = dnsAddr
|
||||||
|
msg.DNSHostName = tlv.SomeRecordT(dnsRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
randRecs, _ := RandSignedRangeRecords(t)
|
||||||
|
if len(randRecs) > 0 {
|
||||||
|
msg.ExtraSignedFields = ExtraSignedFields(randRecs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
// A compile time check to ensure OpenChannel implements the TestMessage
|
// A compile time check to ensure OpenChannel implements the TestMessage
|
||||||
// interface.
|
// interface.
|
||||||
var _ TestMessage = (*OpenChannel)(nil)
|
var _ TestMessage = (*OpenChannel)(nil)
|
||||||
@@ -1851,3 +1998,24 @@ func (c *Error) RandTestMessage(t *rapid.T) Message {
|
|||||||
|
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// genValidHostname generates a random valid hostname according to BOLT #7
|
||||||
|
// rules.
|
||||||
|
func genValidHostname(t *rapid.T) string {
|
||||||
|
// Valid characters: a-z, A-Z, 0-9, -, .
|
||||||
|
validChars := "abcdefghijklmnopqrstuvwxyzABCDE" +
|
||||||
|
"FGHIJKLMNOPQRSTUVWXYZ0123456789-."
|
||||||
|
|
||||||
|
// Generate hostname length between 1 and 255 characters.
|
||||||
|
length := rapid.IntRange(1, 255).Draw(t, "hostname_length")
|
||||||
|
|
||||||
|
hostname := make([]byte, length)
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
charIndex := rapid.IntRange(0, len(validChars)-1).Draw(
|
||||||
|
t, fmt.Sprintf("char_%d", i),
|
||||||
|
)
|
||||||
|
hostname[i] = validChars[charIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(hostname)
|
||||||
|
}
|
||||||
@@ -152,6 +152,19 @@ func RandNodeAlias(t *rapid.T) NodeAlias {
|
|||||||
return alias
|
return alias
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandNodeAlias2 generates a random node alias that is compatible with
|
||||||
|
// NodeAlias2 validation (non-empty, max 32 bytes, valid UTF-8).
|
||||||
|
func RandNodeAlias2(t *rapid.T) NodeAlias2 {
|
||||||
|
// Ensure length is at least 1 to satisfy NodeAlias2 validation
|
||||||
|
aliasLength := rapid.IntRange(1, 32).Draw(t, "aliasLength")
|
||||||
|
|
||||||
|
aliasBytes := rapid.SliceOfN(
|
||||||
|
rapid.SampledFrom([]rune(charset)), aliasLength, aliasLength,
|
||||||
|
).Draw(t, "alias")
|
||||||
|
|
||||||
|
return []byte(string(aliasBytes))
|
||||||
|
}
|
||||||
|
|
||||||
// RandNetAddrs generates random network addresses.
|
// RandNetAddrs generates random network addresses.
|
||||||
func RandNetAddrs(t *rapid.T) []net.Addr {
|
func RandNetAddrs(t *rapid.T) []net.Addr {
|
||||||
numAddresses := rapid.IntRange(0, 5).Draw(t, "numAddresses")
|
numAddresses := rapid.IntRange(0, 5).Draw(t, "numAddresses")
|
||||||
|
|||||||
+5
-5
@@ -22,8 +22,8 @@ type HostAnnouncerConfig struct {
|
|||||||
LookupHost func(string) (net.Addr, error)
|
LookupHost func(string) (net.Addr, error)
|
||||||
|
|
||||||
// AdvertisedIPs is the set of IPs that we've already announced with
|
// AdvertisedIPs is the set of IPs that we've already announced with
|
||||||
// our current NodeAnnouncement. This set will be constructed to avoid
|
// our current NodeAnnouncement1. This set will be constructed to avoid
|
||||||
// unnecessary node NodeAnnouncement updates.
|
// unnecessary node NodeAnnouncement1 updates.
|
||||||
AdvertisedIPs map[string]struct{}
|
AdvertisedIPs map[string]struct{}
|
||||||
|
|
||||||
// AnnounceNewIPs announces a new set of IP addresses for the backing
|
// AnnounceNewIPs announces a new set of IP addresses for the backing
|
||||||
@@ -36,7 +36,7 @@ type HostAnnouncerConfig struct {
|
|||||||
// HostAnnouncer is a sub-system that allows a user to specify a set of hosts
|
// HostAnnouncer is a sub-system that allows a user to specify a set of hosts
|
||||||
// for lnd that will be continually resolved to notice any IP address changes.
|
// for lnd that will be continually resolved to notice any IP address changes.
|
||||||
// If the target IP address for a host changes, then we'll generate a new
|
// If the target IP address for a host changes, then we'll generate a new
|
||||||
// NodeAnnouncement that includes these new IPs.
|
// NodeAnnouncement1 that includes these new IPs.
|
||||||
type HostAnnouncer struct {
|
type HostAnnouncer struct {
|
||||||
cfg HostAnnouncerConfig
|
cfg HostAnnouncerConfig
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ func (h *HostAnnouncer) hostWatcher() {
|
|||||||
// announcement on disk. It returns the updated node announcement given a set
|
// announcement on disk. It returns the updated node announcement given a set
|
||||||
// of updates to be applied to the current node announcement.
|
// of updates to be applied to the current node announcement.
|
||||||
type NodeAnnUpdater func(modifier ...NodeAnnModifier,
|
type NodeAnnUpdater func(modifier ...NodeAnnModifier,
|
||||||
) (lnwire.NodeAnnouncement, error)
|
) (lnwire.NodeAnnouncement1, error)
|
||||||
|
|
||||||
// IPAnnouncer is a factory function that generates a new function that uses
|
// IPAnnouncer is a factory function that generates a new function that uses
|
||||||
// the passed annUpdater function to to announce new IP changes for a given
|
// the passed annUpdater function to to announce new IP changes for a given
|
||||||
@@ -181,7 +181,7 @@ func IPAnnouncer(annUpdater NodeAnnUpdater) func([]net.Addr,
|
|||||||
|
|
||||||
return func(newAddrs []net.Addr, oldAddrs map[string]struct{}) error {
|
return func(newAddrs []net.Addr, oldAddrs map[string]struct{}) error {
|
||||||
_, err := annUpdater(func(
|
_, err := annUpdater(func(
|
||||||
currentNodeAnn *lnwire.NodeAnnouncement) {
|
currentNodeAnn *lnwire.NodeAnnouncement1) {
|
||||||
// To ensure we don't duplicate any addresses, we'll
|
// To ensure we don't duplicate any addresses, we'll
|
||||||
// filter out the same of addresses we should no longer
|
// filter out the same of addresses we should no longer
|
||||||
// advertise.
|
// advertise.
|
||||||
|
|||||||
+19
-17
@@ -16,37 +16,39 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NodeAnnModifier is a closure that makes in-place modifications to an
|
// NodeAnnModifier is a closure that makes in-place modifications to an
|
||||||
// lnwire.NodeAnnouncement.
|
// lnwire.NodeAnnouncement1.
|
||||||
type NodeAnnModifier func(*lnwire.NodeAnnouncement)
|
type NodeAnnModifier func(*lnwire.NodeAnnouncement1)
|
||||||
|
|
||||||
// NodeAnnSetAlias is a functional option that sets the alias of the
|
// NodeAnnSetAlias is a functional option that sets the alias of the
|
||||||
// given node announcement.
|
// given node announcement.
|
||||||
func NodeAnnSetAlias(alias lnwire.NodeAlias) func(*lnwire.NodeAnnouncement) {
|
func NodeAnnSetAlias(alias lnwire.NodeAlias) func(*lnwire.NodeAnnouncement1) {
|
||||||
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
return func(nodeAnn *lnwire.NodeAnnouncement1) {
|
||||||
nodeAnn.Alias = alias
|
nodeAnn.Alias = alias
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAnnSetAddrs is a functional option that allows updating the addresses of
|
// NodeAnnSetAddrs is a functional option that allows updating the addresses of
|
||||||
// the given node announcement.
|
// the given node announcement.
|
||||||
func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement) {
|
func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement1) {
|
||||||
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
return func(nodeAnn *lnwire.NodeAnnouncement1) {
|
||||||
nodeAnn.Addresses = addrs
|
nodeAnn.Addresses = addrs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAnnSetColor is a functional option that sets the color of the
|
// NodeAnnSetColor is a functional option that sets the color of the
|
||||||
// given node announcement.
|
// given node announcement.
|
||||||
func NodeAnnSetColor(newColor color.RGBA) func(*lnwire.NodeAnnouncement) {
|
func NodeAnnSetColor(newColor color.RGBA) func(*lnwire.NodeAnnouncement1) {
|
||||||
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
return func(nodeAnn *lnwire.NodeAnnouncement1) {
|
||||||
nodeAnn.RGBColor = newColor
|
nodeAnn.RGBColor = newColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAnnSetFeatures is a functional option that allows updating the features of
|
// NodeAnnSetFeatures is a functional option that allows updating the features of
|
||||||
// the given node announcement.
|
// the given node announcement.
|
||||||
func NodeAnnSetFeatures(features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement) {
|
func NodeAnnSetFeatures(
|
||||||
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement1) {
|
||||||
|
|
||||||
|
return func(nodeAnn *lnwire.NodeAnnouncement1) {
|
||||||
nodeAnn.Features = features
|
nodeAnn.Features = features
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +56,7 @@ func NodeAnnSetFeatures(features *lnwire.RawFeatureVector) func(*lnwire.NodeAnno
|
|||||||
// NodeAnnSetTimestamp is a functional option that sets the timestamp of the
|
// NodeAnnSetTimestamp is a functional option that sets the timestamp of the
|
||||||
// announcement to the current time, or increments it if the timestamp is
|
// announcement to the current time, or increments it if the timestamp is
|
||||||
// already in the future.
|
// already in the future.
|
||||||
func NodeAnnSetTimestamp(nodeAnn *lnwire.NodeAnnouncement) {
|
func NodeAnnSetTimestamp(nodeAnn *lnwire.NodeAnnouncement1) {
|
||||||
newTimestamp := uint32(time.Now().Unix())
|
newTimestamp := uint32(time.Now().Unix())
|
||||||
if newTimestamp <= nodeAnn.Timestamp {
|
if newTimestamp <= nodeAnn.Timestamp {
|
||||||
// Increment the prior value to ensure the timestamp
|
// Increment the prior value to ensure the timestamp
|
||||||
@@ -65,11 +67,11 @@ func NodeAnnSetTimestamp(nodeAnn *lnwire.NodeAnnouncement) {
|
|||||||
nodeAnn.Timestamp = newTimestamp
|
nodeAnn.Timestamp = newTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignNodeAnnouncement signs the lnwire.NodeAnnouncement provided, which
|
// SignNodeAnnouncement signs the lnwire.NodeAnnouncement1 provided, which
|
||||||
// should be the most recent, valid update, otherwise the timestamp may not
|
// should be the most recent, valid update, otherwise the timestamp may not
|
||||||
// monotonically increase from the prior.
|
// monotonically increase from the prior.
|
||||||
func SignNodeAnnouncement(signer lnwallet.MessageSigner,
|
func SignNodeAnnouncement(signer lnwallet.MessageSigner,
|
||||||
keyLoc keychain.KeyLocator, nodeAnn *lnwire.NodeAnnouncement) error {
|
keyLoc keychain.KeyLocator, nodeAnn *lnwire.NodeAnnouncement1) error {
|
||||||
|
|
||||||
// Create the DER-encoded ECDSA signature over the message digest.
|
// Create the DER-encoded ECDSA signature over the message digest.
|
||||||
sig, err := SignAnnouncement(signer, keyLoc, nodeAnn)
|
sig, err := SignAnnouncement(signer, keyLoc, nodeAnn)
|
||||||
@@ -83,7 +85,7 @@ func SignNodeAnnouncement(signer lnwallet.MessageSigner,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateNodeAnn validates the fields and signature of a node announcement.
|
// ValidateNodeAnn validates the fields and signature of a node announcement.
|
||||||
func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
|
func ValidateNodeAnn(a *lnwire.NodeAnnouncement1) error {
|
||||||
err := ValidateNodeAnnFields(a)
|
err := ValidateNodeAnnFields(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid node announcement fields: %w", err)
|
return fmt.Errorf("invalid node announcement fields: %w", err)
|
||||||
@@ -93,7 +95,7 @@ func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ValidateNodeAnnFields validates the fields of a node announcement.
|
// ValidateNodeAnnFields validates the fields of a node announcement.
|
||||||
func ValidateNodeAnnFields(a *lnwire.NodeAnnouncement) error {
|
func ValidateNodeAnnFields(a *lnwire.NodeAnnouncement1) error {
|
||||||
// Check that it only has at most one DNS address.
|
// Check that it only has at most one DNS address.
|
||||||
hasDNSAddr := false
|
hasDNSAddr := false
|
||||||
for _, addr := range a.Addresses {
|
for _, addr := range a.Addresses {
|
||||||
@@ -120,7 +122,7 @@ func ValidateNodeAnnFields(a *lnwire.NodeAnnouncement) error {
|
|||||||
// ValidateNodeAnnSignature validates the node announcement by ensuring that the
|
// ValidateNodeAnnSignature validates the node announcement by ensuring that the
|
||||||
// attached signature is needed a signature of the node announcement under the
|
// attached signature is needed a signature of the node announcement under the
|
||||||
// specified node public key.
|
// specified node public key.
|
||||||
func ValidateNodeAnnSignature(a *lnwire.NodeAnnouncement) error {
|
func ValidateNodeAnnSignature(a *lnwire.NodeAnnouncement1) error {
|
||||||
// Reconstruct the data of announcement which should be covered by the
|
// Reconstruct the data of announcement which should be covered by the
|
||||||
// signature so we can verify the signature shortly below
|
// signature so we can verify the signature shortly below
|
||||||
data, err := a.DataToSign()
|
data, err := a.DataToSign()
|
||||||
@@ -146,7 +148,7 @@ func ValidateNodeAnnSignature(a *lnwire.NodeAnnouncement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("signature on NodeAnnouncement(%x) is "+
|
return fmt.Errorf("signature on NodeAnnouncement1(%x) is "+
|
||||||
"invalid: %x", nodeKey.SerializeCompressed(),
|
"invalid: %x", nodeKey.SerializeCompressed(),
|
||||||
msgBuf.Bytes())
|
msgBuf.Bytes())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ func SignAnnouncement(signer lnwallet.MessageSigner, keyLoc keychain.KeyLocator,
|
|||||||
data, err = m.DataToSign()
|
data, err = m.DataToSign()
|
||||||
case *lnwire.ChannelUpdate1:
|
case *lnwire.ChannelUpdate1:
|
||||||
data, err = m.DataToSign()
|
data, err = m.DataToSign()
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
data, err = m.DataToSign()
|
data, err = m.DataToSign()
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("can't sign %T message", m)
|
return nil, fmt.Errorf("can't sign %T message", m)
|
||||||
|
|||||||
+4
-4
@@ -329,7 +329,7 @@ type Config struct {
|
|||||||
// GenNodeAnnouncement is used to send our node announcement to the remote
|
// GenNodeAnnouncement is used to send our node announcement to the remote
|
||||||
// on startup.
|
// on startup.
|
||||||
GenNodeAnnouncement func(...netann.NodeAnnModifier) (
|
GenNodeAnnouncement func(...netann.NodeAnnModifier) (
|
||||||
lnwire.NodeAnnouncement, error)
|
lnwire.NodeAnnouncement1, error)
|
||||||
|
|
||||||
// PrunePersistentPeerConnection is used to remove all internal state
|
// PrunePersistentPeerConnection is used to remove all internal state
|
||||||
// related to this peer in the server.
|
// related to this peer in the server.
|
||||||
@@ -2092,7 +2092,7 @@ out:
|
|||||||
idleTimer.Reset(idleTimeout)
|
idleTimer.Reset(idleTimeout)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
// If the NodeAnnouncement has an invalid alias, then
|
// If the NodeAnnouncement1 has an invalid alias, then
|
||||||
// we'll log that error above and continue so we can
|
// we'll log that error above and continue so we can
|
||||||
// continue to read messages from the peer. We do not
|
// continue to read messages from the peer. We do not
|
||||||
// store this error because it is of little debugging
|
// store this error because it is of little debugging
|
||||||
@@ -2213,7 +2213,7 @@ out:
|
|||||||
|
|
||||||
case *lnwire.ChannelUpdate1,
|
case *lnwire.ChannelUpdate1,
|
||||||
*lnwire.ChannelAnnouncement1,
|
*lnwire.ChannelAnnouncement1,
|
||||||
*lnwire.NodeAnnouncement,
|
*lnwire.NodeAnnouncement1,
|
||||||
*lnwire.AnnounceSignatures1,
|
*lnwire.AnnounceSignatures1,
|
||||||
*lnwire.GossipTimestampRange,
|
*lnwire.GossipTimestampRange,
|
||||||
*lnwire.QueryShortChanIDs,
|
*lnwire.QueryShortChanIDs,
|
||||||
@@ -2494,7 +2494,7 @@ func messageSummary(msg lnwire.Message) string {
|
|||||||
msg.ShortChannelID.ToUint64(), msg.MessageFlags,
|
msg.ShortChannelID.ToUint64(), msg.MessageFlags,
|
||||||
msg.ChannelFlags, time.Unix(int64(msg.Timestamp), 0))
|
msg.ChannelFlags, time.Unix(int64(msg.Timestamp), 0))
|
||||||
|
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement1:
|
||||||
return fmt.Sprintf("node=%x, update_time=%v",
|
return fmt.Sprintf("node=%x, update_time=%v",
|
||||||
msg.NodeID, time.Unix(int64(msg.Timestamp), 0))
|
msg.NodeID, time.Unix(int64(msg.Timestamp), 0))
|
||||||
|
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ type server struct {
|
|||||||
// currentNodeAnn is the node announcement that has been broadcast to
|
// currentNodeAnn is the node announcement that has been broadcast to
|
||||||
// the network upon startup, if the attributes of the node (us) has
|
// the network upon startup, if the attributes of the node (us) has
|
||||||
// changed since last start.
|
// changed since last start.
|
||||||
currentNodeAnn *lnwire.NodeAnnouncement
|
currentNodeAnn *lnwire.NodeAnnouncement1
|
||||||
|
|
||||||
// chansToRestore is the set of channels that upon starting, the server
|
// chansToRestore is the set of channels that upon starting, the server
|
||||||
// should attempt to restore/recover.
|
// should attempt to restore/recover.
|
||||||
@@ -1069,7 +1069,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
NotifyWhenOnline: s.NotifyWhenOnline,
|
NotifyWhenOnline: s.NotifyWhenOnline,
|
||||||
NotifyWhenOffline: s.NotifyWhenOffline,
|
NotifyWhenOffline: s.NotifyWhenOffline,
|
||||||
FetchSelfAnnouncement: s.getNodeAnnouncement,
|
FetchSelfAnnouncement: s.getNodeAnnouncement,
|
||||||
UpdateSelfAnnouncement: func() (lnwire.NodeAnnouncement,
|
UpdateSelfAnnouncement: func() (lnwire.NodeAnnouncement1,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
return s.genNodeAnnouncement(nil)
|
return s.genNodeAnnouncement(nil)
|
||||||
@@ -1466,7 +1466,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
ChannelDB: s.chanStateDB,
|
ChannelDB: s.chanStateDB,
|
||||||
FeeEstimator: cc.FeeEstimator,
|
FeeEstimator: cc.FeeEstimator,
|
||||||
SignMessage: cc.MsgSigner.SignMessage,
|
SignMessage: cc.MsgSigner.SignMessage,
|
||||||
CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement,
|
CurrentNodeAnnouncement: func() (lnwire.NodeAnnouncement1,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
return s.genNodeAnnouncement(nil)
|
return s.genNodeAnnouncement(nil)
|
||||||
@@ -1796,7 +1796,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
AdvertisedIPs: advertisedIPs,
|
AdvertisedIPs: advertisedIPs,
|
||||||
AnnounceNewIPs: netann.IPAnnouncer(
|
AnnounceNewIPs: netann.IPAnnouncer(
|
||||||
func(modifier ...netann.NodeAnnModifier) (
|
func(modifier ...netann.NodeAnnModifier) (
|
||||||
lnwire.NodeAnnouncement, error) {
|
lnwire.NodeAnnouncement1, error) {
|
||||||
|
|
||||||
return s.genNodeAnnouncement(
|
return s.genNodeAnnouncement(
|
||||||
nil, modifier...,
|
nil, modifier...,
|
||||||
@@ -3306,7 +3306,7 @@ func (s *server) createNewHiddenService(ctx context.Context) error {
|
|||||||
// Now that the onion service has been created, we'll add the onion
|
// Now that the onion service has been created, we'll add the onion
|
||||||
// address it can be reached at to our list of advertised addresses.
|
// address it can be reached at to our list of advertised addresses.
|
||||||
newNodeAnn, err := s.genNodeAnnouncement(
|
newNodeAnn, err := s.genNodeAnnouncement(
|
||||||
nil, func(currentAnn *lnwire.NodeAnnouncement) {
|
nil, func(currentAnn *lnwire.NodeAnnouncement1) {
|
||||||
currentAnn.Addresses = append(currentAnn.Addresses, addr)
|
currentAnn.Addresses = append(currentAnn.Addresses, addr)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -3357,7 +3357,7 @@ func (s *server) findChannel(node *btcec.PublicKey, chanID lnwire.ChannelID) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getNodeAnnouncement fetches the current, fully signed node announcement.
|
// getNodeAnnouncement fetches the current, fully signed node announcement.
|
||||||
func (s *server) getNodeAnnouncement() lnwire.NodeAnnouncement {
|
func (s *server) getNodeAnnouncement() lnwire.NodeAnnouncement1 {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
@@ -3368,7 +3368,7 @@ func (s *server) getNodeAnnouncement() lnwire.NodeAnnouncement {
|
|||||||
// announcement. The time stamp of the announcement will be updated in order
|
// announcement. The time stamp of the announcement will be updated in order
|
||||||
// to ensure it propagates through the network.
|
// to ensure it propagates through the network.
|
||||||
func (s *server) genNodeAnnouncement(features *lnwire.RawFeatureVector,
|
func (s *server) genNodeAnnouncement(features *lnwire.RawFeatureVector,
|
||||||
modifiers ...netann.NodeAnnModifier) (lnwire.NodeAnnouncement, error) {
|
modifiers ...netann.NodeAnnModifier) (lnwire.NodeAnnouncement1, error) {
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
@@ -3386,7 +3386,7 @@ func (s *server) genNodeAnnouncement(features *lnwire.RawFeatureVector,
|
|||||||
}
|
}
|
||||||
err := s.featureMgr.UpdateFeatureSets(proposedFeatures)
|
err := s.featureMgr.UpdateFeatureSets(proposedFeatures)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return lnwire.NodeAnnouncement{}, err
|
return lnwire.NodeAnnouncement1{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we could successfully update our feature manager, add
|
// If we could successfully update our feature manager, add
|
||||||
@@ -3411,7 +3411,7 @@ func (s *server) genNodeAnnouncement(features *lnwire.RawFeatureVector,
|
|||||||
s.nodeSigner, s.identityKeyLoc, &newNodeAnn,
|
s.nodeSigner, s.identityKeyLoc, &newNodeAnn,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return lnwire.NodeAnnouncement{}, err
|
return lnwire.NodeAnnouncement1{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If signing succeeds, update the current announcement.
|
// If signing succeeds, update the current announcement.
|
||||||
@@ -3501,7 +3501,7 @@ func (s *server) establishPersistentConnections(ctx context.Context) error {
|
|||||||
|
|
||||||
// After checking our previous connections for addresses to connect to,
|
// After checking our previous connections for addresses to connect to,
|
||||||
// iterate through the nodes in our channel graph to find addresses
|
// iterate through the nodes in our channel graph to find addresses
|
||||||
// that have been added via NodeAnnouncement messages.
|
// that have been added via NodeAnnouncement1 messages.
|
||||||
// TODO(roasbeef): instead iterate over link nodes and query graph for
|
// TODO(roasbeef): instead iterate over link nodes and query graph for
|
||||||
// each of the nodes.
|
// each of the nodes.
|
||||||
graphAddrs := make(map[string]*nodeAddresses)
|
graphAddrs := make(map[string]*nodeAddresses)
|
||||||
@@ -4394,7 +4394,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq,
|
|||||||
TowerClient: towerClient,
|
TowerClient: towerClient,
|
||||||
DisconnectPeer: s.DisconnectPeer,
|
DisconnectPeer: s.DisconnectPeer,
|
||||||
GenNodeAnnouncement: func(...netann.NodeAnnModifier) (
|
GenNodeAnnouncement: func(...netann.NodeAnnModifier) (
|
||||||
lnwire.NodeAnnouncement, error) {
|
lnwire.NodeAnnouncement1, error) {
|
||||||
|
|
||||||
return s.genNodeAnnouncement(nil)
|
return s.genNodeAnnouncement(nil)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
|
|||||||
tcpResolver lncfg.TCPResolver,
|
tcpResolver lncfg.TCPResolver,
|
||||||
genInvoiceFeatures func() *lnwire.FeatureVector,
|
genInvoiceFeatures func() *lnwire.FeatureVector,
|
||||||
genAmpInvoiceFeatures func() *lnwire.FeatureVector,
|
genAmpInvoiceFeatures func() *lnwire.FeatureVector,
|
||||||
getNodeAnnouncement func() lnwire.NodeAnnouncement,
|
getNodeAnnouncement func() lnwire.NodeAnnouncement1,
|
||||||
updateNodeAnnouncement func(ctx context.Context,
|
updateNodeAnnouncement func(ctx context.Context,
|
||||||
features *lnwire.RawFeatureVector,
|
features *lnwire.RawFeatureVector,
|
||||||
modifiers ...netann.NodeAnnModifier) error,
|
modifiers ...netann.NodeAnnModifier) error,
|
||||||
|
|||||||
Reference in new issue
Block a user