mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 14:22:37 +01:00
lnrpc/peers: handle alias changes in updateNodeAnnouncement
This commit is contained in:
parent
e4e0935816
commit
ce4813940d
4 changed files with 165 additions and 6 deletions
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/netann"
|
||||
"google.golang.org/grpc"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
|
@ -168,7 +169,7 @@ func (s *Server) UpdateNodeAnnouncement(_ context.Context,
|
|||
resp := &NodeAnnouncementUpdateResponse{}
|
||||
nodeModifiers := make([]netann.NodeAnnModifier, 0)
|
||||
|
||||
_, err := s.cfg.GetNodeAnnouncement()
|
||||
currentNodeAnn, err := s.cfg.GetNodeAnnouncement()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get current node "+
|
||||
"announcement: %v", err)
|
||||
|
@ -178,7 +179,24 @@ func (s *Server) UpdateNodeAnnouncement(_ context.Context,
|
|||
|
||||
// TODO(positiveblue): apply color modifications
|
||||
|
||||
// TODO(positiveblue): apply alias modifications
|
||||
if req.Alias != "" {
|
||||
alias, err := lnwire.NewNodeAlias(req.Alias)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid alias value: %v", err)
|
||||
}
|
||||
if alias != currentNodeAnn.Alias {
|
||||
resp.Ops = append(resp.Ops, &lnrpc.Op{
|
||||
Entity: "alias",
|
||||
Actions: []string{
|
||||
fmt.Sprintf("changed to %v", alias),
|
||||
},
|
||||
})
|
||||
nodeModifiers = append(
|
||||
nodeModifiers,
|
||||
netann.NodeAnnSetAlias(alias),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(positiveblue): apply addresses modifications
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
|
@ -1856,3 +1857,33 @@ func assertAnchorOutputLost(t *harnessTest, node *lntest.HarnessNode,
|
|||
}, defaultTimeout)
|
||||
require.NoError(t.t, err, "anchor doesn't show as being lost")
|
||||
}
|
||||
|
||||
// assertNodeAnnouncement compares that two node announcements match.
|
||||
func assertNodeAnnouncement(t *harnessTest, n1, n2 *lnrpc.NodeUpdate) {
|
||||
// Alias should match.
|
||||
require.Equal(t.t, n1.Alias, n2.Alias, "alias don't match")
|
||||
}
|
||||
|
||||
// assertUpdateNodeAnnouncementResponse is a helper function to assert
|
||||
// the response expected values.
|
||||
func assertUpdateNodeAnnouncementResponse(t *harnessTest,
|
||||
response *peersrpc.NodeAnnouncementUpdateResponse,
|
||||
expectedOps map[string]int) {
|
||||
|
||||
require.Equal(
|
||||
t.t, len(response.Ops), len(expectedOps),
|
||||
"unexpected number of Ops updating dave's node announcement",
|
||||
)
|
||||
|
||||
ops := make(map[string]int, len(response.Ops))
|
||||
for _, op := range response.Ops {
|
||||
ops[op.Entity] = len(op.Actions)
|
||||
}
|
||||
|
||||
for k, v := range expectedOps {
|
||||
if v != ops[k] {
|
||||
t.Fatalf("unexpected number of actions for operation "+
|
||||
"%s: got %d wanted %d", k, ops[k], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -769,16 +770,80 @@ func subscribeGraphNotifications(ctxb context.Context, t *harnessTest,
|
|||
}
|
||||
}
|
||||
|
||||
// waitForNodeAnnUpdates monitors the nodeAnnUpdates until we get one for
|
||||
// the expected node and asserts that has the expected information.
|
||||
func waitForNodeAnnUpdates(graphSub graphSubscription, nodePubKey string,
|
||||
expectedUpdate *lnrpc.NodeUpdate, t *harnessTest) {
|
||||
|
||||
for {
|
||||
select {
|
||||
case graphUpdate := <-graphSub.updateChan:
|
||||
for _, update := range graphUpdate.NodeUpdates {
|
||||
if update.IdentityKey == nodePubKey {
|
||||
assertNodeAnnouncement(
|
||||
t, update, expectedUpdate,
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
case err := <-graphSub.errChan:
|
||||
t.Fatalf("unable to recv graph update: %v", err)
|
||||
case <-time.After(defaultTimeout):
|
||||
t.Fatalf("did not receive node ann update")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// testUpdateNodeAnnouncement ensures that the RPC endpoint validates
|
||||
// the requests correctly and that the new node announcement is brodcasted
|
||||
// with the right information after updating our node.
|
||||
func testUpdateNodeAnnouncement(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
ctxb := context.Background()
|
||||
// context timeout for the whole test.
|
||||
ctxt, cancel := context.WithTimeout(
|
||||
context.Background(), defaultTimeout,
|
||||
)
|
||||
defer cancel()
|
||||
|
||||
// Launch notification clients for alice, such that we can
|
||||
// get notified when there are updates in the graph.
|
||||
aliceSub := subscribeGraphNotifications(ctxt, t, net.Alice)
|
||||
defer close(aliceSub.quit)
|
||||
|
||||
var lndArgs []string
|
||||
dave := net.NewNode(t.t, "Dave", lndArgs)
|
||||
defer shutdownAndAssert(net, t, dave)
|
||||
|
||||
// Get dave default information so we can compare
|
||||
// it lately with the brodcasted updates.
|
||||
nodeInfoReq := &lnrpc.GetInfoRequest{}
|
||||
resp, err := dave.GetInfo(ctxt, nodeInfoReq)
|
||||
require.NoError(t.t, err, "unable to get dave's information")
|
||||
|
||||
defaultDaveNodeAnn := &lnrpc.NodeUpdate{
|
||||
Alias: resp.Alias,
|
||||
}
|
||||
|
||||
// Dave must have an open channel before he can send a node
|
||||
// announcement, so we open a channel with Bob.
|
||||
net.ConnectNodes(t.t, net.Bob, dave)
|
||||
|
||||
// Go ahead and open a channel between Bob and Dave. This
|
||||
// ensures that Alice receives the node announcement from Bob as part of
|
||||
// the announcement broadcast.
|
||||
chanPoint := openChannelAndAssert(
|
||||
t, net, net.Bob, dave,
|
||||
lntest.OpenChannelParams{
|
||||
Amt: 1000000,
|
||||
},
|
||||
)
|
||||
require.NoError(t.t, err, "unexpected error opening a channel")
|
||||
|
||||
// Wait for Alice to receive dave's node announcement with the default
|
||||
// values.
|
||||
waitForNodeAnnUpdates(
|
||||
aliceSub, dave.PubKeyStr, defaultDaveNodeAnn, t,
|
||||
)
|
||||
|
||||
// We cannot differentiate between requests with Alias = "" and requests
|
||||
// that do not provide that field. If a user sets Alias = "" in the request
|
||||
// the field will simply be ignored. The request must fail because no
|
||||
|
@ -786,9 +851,46 @@ func testUpdateNodeAnnouncement(net *lntest.NetworkHarness, t *harnessTest) {
|
|||
invalidNodeAnnReq := &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
Alias: "",
|
||||
}
|
||||
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
_, err := dave.UpdateNodeAnnouncement(ctxt, invalidNodeAnnReq)
|
||||
_, err = dave.UpdateNodeAnnouncement(ctxt, invalidNodeAnnReq)
|
||||
require.Error(t.t, err, "requests without modifiers should field")
|
||||
|
||||
// Alias too long.
|
||||
invalidNodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
Alias: strings.Repeat("a", 50),
|
||||
}
|
||||
|
||||
_, err = dave.UpdateNodeAnnouncement(ctxt, invalidNodeAnnReq)
|
||||
require.Error(t.t, err, "failed to validate an invalid alias for an "+
|
||||
"update node announcement request")
|
||||
|
||||
// Update Node.
|
||||
newAlias := "new-alias"
|
||||
|
||||
nodeAnnReq := &peersrpc.NodeAnnouncementUpdateRequest{
|
||||
Alias: newAlias,
|
||||
}
|
||||
|
||||
response, err := dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
|
||||
require.NoError(t.t, err, "unable to update dave's node announcement")
|
||||
|
||||
expectedOps := map[string]int{
|
||||
"alias": 1,
|
||||
}
|
||||
assertUpdateNodeAnnouncementResponse(t, response, expectedOps)
|
||||
|
||||
// After updating the node we expect the update to contain
|
||||
// the requested color, requested alias and the new added addresses.
|
||||
newDaveNodeAnn := &lnrpc.NodeUpdate{
|
||||
Alias: newAlias,
|
||||
}
|
||||
|
||||
// We'll then wait for Alice to receive dave's node announcement
|
||||
// with the new values.
|
||||
waitForNodeAnnUpdates(
|
||||
aliceSub, dave.PubKeyStr, newDaveNodeAnn, t,
|
||||
)
|
||||
|
||||
// Close the channel between Bob and Dave.
|
||||
closeChannelAndAssert(t, net, net.Bob, chanPoint, false)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,14 @@ import (
|
|||
// lnwire.NodeAnnouncement.
|
||||
type NodeAnnModifier func(*lnwire.NodeAnnouncement)
|
||||
|
||||
// NodeAnnSetAlias is a functional option that sets the alias of the
|
||||
// given node announcment.
|
||||
func NodeAnnSetAlias(alias lnwire.NodeAlias) func(*lnwire.NodeAnnouncement) {
|
||||
return func(nodeAnn *lnwire.NodeAnnouncement) {
|
||||
nodeAnn.Alias = alias
|
||||
}
|
||||
}
|
||||
|
||||
// NodeAnnSetAddrs is a functional option that allows updating the addresses of
|
||||
// the given node announcement.
|
||||
func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement) {
|
||||
|
|
Loading…
Add table
Reference in a new issue