Skip to content

Commit

Permalink
Merge 94486ad into fe0a7b6
Browse files Browse the repository at this point in the history
  • Loading branch information
blico committed Sep 12, 2017
2 parents fe0a7b6 + 94486ad commit f22c84c
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 31 deletions.
56 changes: 54 additions & 2 deletions lnd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2709,7 +2709,7 @@ func testGraphTopologyNotifications(net *networkHarness, t *harnessTest) {
"sent")
}

// For the final portion of the test, we'll ensure that once a new node
// For the next portion of the test, we'll ensure that once a new node
// appears in the network, the proper notification is dispatched. Note
// that a node that does not have any channels open is ignored, so first
// we disconnect Alice and Bob, open a channel between Bob and Carol,
Expand Down Expand Up @@ -2744,7 +2744,7 @@ func testGraphTopologyNotifications(net *networkHarness, t *harnessTest) {

// We should receive an update advertising the newly connected node,
// Bob's new node announcement, and the channel between Bob and Carol.
for i := 0; i < 3; i++ {
for i := 0; i < 4; i++ {
select {
case graphUpdate := <-graphUpdates:

Expand Down Expand Up @@ -2790,6 +2790,58 @@ func testGraphTopologyNotifications(net *networkHarness, t *harnessTest) {
ctxt, _ = context.WithTimeout(context.Background(), timeout)
closeChannelAndAssert(ctxt, t, net, net.Bob, chanPoint, false)

// Finally, we will test that when a node starts up, a new node announcement
// is only propagated through the network when configuration options have
// changed the node announcement since the last instance of the node.

// First restart Bob with no new config changes
if err := net.RestartNode(net.Bob, nil); err != nil {
t.Fatalf("unable to restart Bob's node: %v", err)
}

if err := net.ConnectNodes(ctxb, net.Alice, net.Bob); err != nil {
t.Fatalf("unable to connect alice to bob: %v", err)
}

// Now restart Bob and add a new IP address to its config options
if err := net.RestartNode(net.Bob, func() error {
net.Bob.cfg.ExternalIPs = []string{"127.0.0.1"}
return nil
}); err != nil {
t.Fatalf("unable to restart Bob's node: %v", err)
}

if err := net.ConnectNodes(ctxb, net.Alice, net.Bob); err != nil {
t.Fatalf("unable to connect alice to bob: %v", err)
}

// Even though we restarted Bob twice, we only expect one node announcement
// from when Bob was restarted with config changes.
numBobAnnRecv := 0
for i := 0; i < 2; i++ {
select {
case graphUpdate := <-graphUpdates:

if len(graphUpdate.NodeUpdates) > 0 {
nodeUpdate := graphUpdate.NodeUpdates[0]
switch nodeUpdate.IdentityKey {
case net.Bob.PubKeyStr:
numBobAnnRecv++
if numBobAnnRecv > 1 {
t.Fatalf("unexpected amount of node updates received from Bob")
}
default:
t.Fatalf("unknown node update pubey: %v",
nodeUpdate.IdentityKey)
}
}
case <-time.After(time.Second * 10):
if numBobAnnRecv == 0 {
t.Fatalf("timeout waiting for graph notification %v", i)
}
}
}

close(quit)

// Finally, shutdown carol as our test has concluded successfully.
Expand Down
38 changes: 37 additions & 1 deletion lnwire/node_announcement.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (n NodeAlias) String() string {

// NodeAnnouncement message is used to announce the presence of a Lightning
// node and also to signal that the node is accepting incoming connections.
// Each NodeAnnouncement authenticating the advertised information within the
// Each node authenticates the advertised information within the
// announcement via a signature using the advertised node pubkey.
type NodeAnnouncement struct {
// Signature is used to prove the ownership of node id.
Expand Down Expand Up @@ -152,3 +152,39 @@ func (a *NodeAnnouncement) DataToSign() ([]byte, error) {

return w.Bytes(), nil
}

// CompareNodes compares the configurable fields within two NodeAnnouncement
// objects, and returns whether they are equal or not.
func (a *NodeAnnouncement) CompareNodes(b *NodeAnnouncement) bool {
if !a.NodeID.IsEqual(b.NodeID) {
return false
}
if a.Alias != b.Alias {
return false
}
if a.RGBColor != b.RGBColor {
return false
}

// When comparing Address arrays the order does not matter.
m := make(map[net.Addr]bool)
for _, addr := range a.Addresses {
m[addr] = true
}
for _, addr := range b.Addresses {
if _, eq := m[addr]; !eq {
return false
}
}

if len(a.Features.flags) != len(b.Features.flags) {
return false
}
for index, aFlag := range a.Features.flags {
if bFlag, exist := b.Features.flags[index]; !exist || aFlag != bFlag {
return false
}
}

return true
}
88 changes: 60 additions & 28 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,47 +203,79 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
selfAddrs = append(selfAddrs, lnAddr)
}

chanGraph := chanDB.ChannelGraph()

// TODO(roasbeef): make alias configurable
alias, err := lnwire.NewNodeAlias(hex.EncodeToString(serializedPubKey[:10]))
if err != nil {
return nil, err
}
selfNode := &channeldb.LightningNode{
HaveNodeAnnouncement: true,
LastUpdate: time.Now(),
Addresses: selfAddrs,
PubKey: privKey.PubKey(),
Alias: alias.String(),
Features: globalFeatures,
}

// If our information has changed since our last boot, then we'll
// re-sign our node announcement so a fresh authenticated version of it
// can be propagated throughout the network upon startup.
//
// TODO(roasbeef): don't always set timestamp above to _now.
timeStamp := time.Now()
nodeAnn := &lnwire.NodeAnnouncement{
Timestamp: uint32(selfNode.LastUpdate.Unix()),
Addresses: selfNode.Addresses,
NodeID: selfNode.PubKey,
Timestamp: uint32(timeStamp.Unix()),
Addresses: selfAddrs,
NodeID: privKey.PubKey(),
Alias: alias,
Features: selfNode.Features,
Features: globalFeatures,
}
selfNode.AuthSig, err = discovery.SignAnnouncement(s.nodeSigner,
s.identityPriv.PubKey(), nodeAnn,
)
if err != nil {
return nil, fmt.Errorf("unable to generate signature for "+
"self node announcement: %v", err)

updateNodeAnn := true

chanGraph := chanDB.ChannelGraph()

// Try to retrieve the old source node from disk. During startup it
// is possible for there to be no source node, and this should not be
// treated as an error.
oldNode, err := chanGraph.SourceNode()
if err != nil && err != channeldb.ErrSourceNodeNotSet {
return nil, fmt.Errorf("unable to read old source node from disk")
}

if oldNode != nil {
oldAlias, err := lnwire.NewNodeAlias(oldNode.Alias)
if err != nil {
return nil, err
}

oldNodeAnn := &lnwire.NodeAnnouncement{
Timestamp: uint32(oldNode.LastUpdate.Unix()),
Addresses: oldNode.Addresses,
NodeID: oldNode.PubKey,
Alias: oldAlias,
Features: oldNode.Features,
}

// If the nodes are not equal than there have been config changes
// and we should propagate the updated node.
updateNodeAnn = !nodeAnn.CompareNodes(oldNodeAnn)
}

if err := chanGraph.SetSourceNode(selfNode); err != nil {
return nil, fmt.Errorf("can't set self node: %v", err)
// If our information has changed since our last boot, then we'll
// re-sign our node announcement so a fresh authenticated version of it
// can be propagated throughout the network upon startup.
if updateNodeAnn {
selfNode := &channeldb.LightningNode{
HaveNodeAnnouncement: true,
LastUpdate: timeStamp,
Addresses: selfAddrs,
PubKey: privKey.PubKey(),
Alias: alias.String(),
Features: globalFeatures,
}
selfNode.AuthSig, err = discovery.SignAnnouncement(s.nodeSigner,
s.identityPriv.PubKey(), nodeAnn,
)
if err != nil {
return nil, fmt.Errorf("unable to generate signature for "+
"self node announcement: %v", err)
}

if err := chanGraph.SetSourceNode(selfNode); err != nil {
return nil, fmt.Errorf("can't set self node: %v", err)
}

nodeAnn.Signature = selfNode.AuthSig
}

nodeAnn.Signature = selfNode.AuthSig
s.currentNodeAnn = nodeAnn

s.chanRouter, err = routing.New(routing.Config{
Expand Down

0 comments on commit f22c84c

Please sign in to comment.