Merge pull request #5587 from positiveblue/5466-update-node-announcement-data

lnrpc: Add UpdateNodeAnnouncement endpoint
This commit is contained in:
Olaoluwa Osuntokun authored and GitHub committed 2022-04-11 22:32:12 -04:00
commit 2fd900b172
40 files changed
+2348 -112

No files matched your search

+1
View File
@@ -17,6 +17,7 @@ run:
- chainrpc
- dev
- invoicesrpc
- peersrpc
- signrpc
- walletrpc
- watchtowerrpc
+1
View File
@@ -400,6 +400,7 @@ func main() {
app.Commands = append(app.Commands, watchtowerCommands()...)
app.Commands = append(app.Commands, wtclientCommands()...)
app.Commands = append(app.Commands, devCommands()...)
app.Commands = append(app.Commands, peersCommands()...)
if err := app.Run(os.Args); err != nil {
fatal(err)
+162
View File
@@ -0,0 +1,162 @@
//go:build peersrpc
// +build peersrpc
package main
import (
"fmt"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/urfave/cli"
)
// peersCommands will return the set of commands to enable for peersrpc
// builds.
func peersCommands() []cli.Command {
return []cli.Command{
{
Name: "peers",
Category: "Peers",
Usage: "Interacts with the other nodes of the " +
"newtwork",
Subcommands: []cli.Command{
updateNodeAnnouncementCommand,
},
},
}
}
func getPeersClient(ctx *cli.Context) (peersrpc.PeersClient, func()) {
conn := getClientConn(ctx, false)
cleanUp := func() {
conn.Close()
}
return peersrpc.NewPeersClient(conn), cleanUp
}
var updateNodeAnnouncementCommand = cli.Command{
Name: "updatenodeannouncement",
Category: "Peers",
Usage: "update and brodcast a new node announcement",
Description: `
Update the node's information and broadcast a new node announcement.
Add or remove addresses where your node can be reached at, change the
alias/color of the node or enable/disable supported feature bits without
restarting the node. A node announcement with the new information will
be created and brodcasted to the network.`,
ArgsUsage: "[--address_add=] [--address_remove=] [--alias=] " +
"[--color=] [--feature_bit_add=] [--feature_bit_remove=]",
Flags: []cli.Flag{
cli.StringSliceFlag{
Name: "address_add",
Usage: "a new address that should be added to the " +
"set of URIs of this node. Can be set " +
"multiple times in the same command",
},
cli.StringSliceFlag{
Name: "address_remove",
Usage: "an address that needs to be removed from the " +
"set of URIs of this node. Can be set " +
"multiple times in the same command",
},
cli.StringFlag{
Name: "alias",
Usage: "the new alias for this node, e.g. \"bob\"",
},
cli.StringFlag{
Name: "color",
Usage: "the new color for this node, e.g. #c42a81",
},
cli.Int64SliceFlag{
Name: "feature_bit_add",
Usage: "a feature bit index that needs to be enabled. " +
"Can be set multiple times in the same command",
},
cli.Int64SliceFlag{
Name: "feature_bit_remove",
Usage: "a feature bit that needs to be disabled" +
"Can be set multiple times in the same command",
},
},
Action: actionDecorator(updateNodeAnnouncement),
}
func updateNodeAnnouncement(ctx *cli.Context) error {
ctxc := getContext()
client, cleanUp := getPeersClient(ctx)
defer cleanUp()
change := false
req := &peersrpc.NodeAnnouncementUpdateRequest{}
if ctx.IsSet("address_add") {
change = true
for _, addr := range ctx.StringSlice("address_add") {
action := &peersrpc.UpdateAddressAction{
Action: peersrpc.UpdateAction_ADD,
Address: addr,
}
req.AddressUpdates = append(req.AddressUpdates, action)
}
}
if ctx.IsSet("address_remove") {
change = true
for _, addr := range ctx.StringSlice("address_remove") {
action := &peersrpc.UpdateAddressAction{
Action: peersrpc.UpdateAction_REMOVE,
Address: addr,
}
req.AddressUpdates = append(req.AddressUpdates, action)
}
}
if ctx.IsSet("alias") {
change = true
req.Alias = ctx.String("alias")
}
if ctx.IsSet("color") {
change = true
req.Color = ctx.String("color")
}
if ctx.IsSet("feature_bit_add") {
change = true
for _, feature := range ctx.IntSlice("feature_bit_add") {
action := &peersrpc.UpdateFeatureAction{
Action: peersrpc.UpdateAction_ADD,
FeatureBit: lnrpc.FeatureBit(feature),
}
req.FeatureUpdates = append(req.FeatureUpdates, action)
}
}
if ctx.IsSet("feature_bit_remove") {
change = true
for _, feature := range ctx.IntSlice("feature_bit_remove") {
action := &peersrpc.UpdateFeatureAction{
Action: peersrpc.UpdateAction_REMOVE,
FeatureBit: lnrpc.FeatureBit(feature),
}
req.FeatureUpdates = append(req.FeatureUpdates, action)
}
}
if !change {
return fmt.Errorf("no changes for the node information " +
"detected")
}
resp, err := client.UpdateNodeAnnouncement(ctxc, req)
if err != nil {
return err
}
printRespJSON(resp)
return nil
}
+11
View File
@@ -0,0 +1,11 @@
//go:build !peersrpc
// +build !peersrpc
package main
import "github.com/urfave/cli"
// peersCommands will return nil for non-peersrpc builds.
func peersCommands() []cli.Command {
return nil
}
+2
View File
@@ -35,6 +35,7 @@ import (
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnwallet"
@@ -516,6 +517,7 @@ func DefaultConfig() Config {
SubRPCServers: &subRPCServerConfigs{
SignRPC: &signrpc.Config{},
RouterRPC: routerrpc.DefaultConfig(),
PeersRPC: &peersrpc.Config{},
},
Autopilot: &lncfg.AutoPilot{
MaxChannels: 5,
+1 -1
View File
@@ -22,7 +22,7 @@ COPY . /go/src/github.com/lightningnetwork/lnd
RUN cd /go/src/github.com/lightningnetwork/lnd \
&& make \
&& make install tags="signrpc walletrpc chainrpc invoicesrpc"
&& make install tags="signrpc walletrpc chainrpc invoicesrpc peersrpc"
# Start a new, final image to reduce size.
FROM alpine as final
@@ -27,6 +27,9 @@ then watch it on chain. Taproot script spends are also supported through the
* [Update description for `state` command](https://github.com/lightningnetwork/lnd/pull/6237).
* Add [update node announcement](https://github.com/lightningnetwork/lnd/pull/5587)
for updating and propagating node information.
## Bug Fixes
* [Pipelining an UpdateFulfillHTLC message now only happens when the related UpdateAddHTLC is locked-in.](https://github.com/lightningnetwork/lnd/pull/6246)
@@ -175,6 +178,8 @@ then watch it on chain. Taproot script spends are also supported through the
* [Improve validation of a PSBT packet when handling a request to finalize it.](https://github.com/lightningnetwork/lnd/pull/6217)
* [Add new Peers subserver](https://github.com/lightningnetwork/lnd/pull/5587) with a new endpoint for updating the `NodeAnnouncement` data without having to restart the node.
## Documentation
* Improved instructions on [how to build lnd for mobile](https://github.com/lightningnetwork/lnd/pull/6085).
+5
View File
@@ -141,6 +141,11 @@ func (m *Manager) GetRaw(set Set) *lnwire.RawFeatureVector {
return lnwire.NewRawFeatureVector()
}
// SetRaw sets a new raw feature vector for the given set.
func (m *Manager) SetRaw(set Set, raw *lnwire.RawFeatureVector) {
m.fsets[set] = raw
}
// Get returns a feature vector for the passed set. If no set is known, an empty
// feature vector is returned.
func (m *Manager) Get(set Set) *lnwire.FeatureVector {
+2 -18
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This means the
// log is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var log btclog.Logger
@@ -21,25 +21,9 @@ func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info. This
// UseLogger uses a specified Logger to output package logging info. This
// should be used in preference to SetLogWriter if the caller is also using
// btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
+1 -17
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) {
log = logger
}
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
+1 -1
View File
@@ -48,7 +48,7 @@ function generate() {
--custom_opt="$opts" \
lightning.proto stateservice.proto walletunlocker.proto
PACKAGES="autopilotrpc chainrpc invoicesrpc routerrpc signrpc verrpc walletrpc watchtowerrpc wtclientrpc devrpc"
PACKAGES="autopilotrpc chainrpc invoicesrpc peersrpc routerrpc signrpc verrpc walletrpc watchtowerrpc wtclientrpc devrpc"
for package in $PACKAGES; do
# Special import for the wallet kit.
manual_import=""
+2 -2
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This means the
// log is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var log btclog.Logger
@@ -21,7 +21,7 @@ func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info. This
// UseLogger uses a specified Logger to output package logging info. This
// should be used in preference to SetLogWriter if the caller is also using
// btclog.
func UseLogger(logger btclog.Logger) {
+29
View File
@@ -0,0 +1,29 @@
//go:build peersrpc
// +build peersrpc
package peersrpc
import (
"net"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/netann"
)
// Config is the primary configuration struct for the peers RPC subserver.
// It contains all the items required for the server to carry out its duties.
// The fields with struct tags are meant to be parsed as normal configuration
// options, while if able to be populated, the latter fields MUST also be
// specified.
type Config struct {
// GetNodeAnnouncement is used to send our retrieve the current
// node announcement information.
GetNodeAnnouncement func() (lnwire.NodeAnnouncement, error)
// ParseAddr parses an address from its string format to a net.Addr.
ParseAddr func(addr string) (net.Addr, error)
// UpdateNodeAnnouncement updates our node announcement applying the
// given NodeAnnModifiers and broadcasts the new version to the network.
UpdateNodeAnnouncement func(...netann.NodeAnnModifier) error
}
+7
View File
@@ -0,0 +1,7 @@
//go:build !peersrpc
// +build !peersrpc
package peersrpc
// Config is empty for non-peersrpc builds.
type Config struct{}
+55
View File
@@ -0,0 +1,55 @@
//go:build peersrpc
// +build peersrpc
package peersrpc
import (
"fmt"
"github.com/lightningnetwork/lnd/lnrpc"
)
// createNewSubServer is a helper method that will create the new sub server
// given the main config dispatcher method. If we're unable to find the config
// that is meant for us in the config dispatcher, then we'll exit with an
// error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
*Server, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our
// subServerName name. If we can't find this, then we'll exit with an
// error, as we're unable to properly initialize ourselves without this
// config.
subServerConf, ok := configRegistry.FetchConfig(subServerName)
if !ok {
return nil, nil, fmt.Errorf("unable to find config for "+
"subserver type %s", subServerName)
}
// Now that we've found an object mapping to our service name, we'll
// ensure that it's the type we need.
config, ok := subServerConf.(*Config)
if !ok {
return nil, nil, fmt.Errorf("wrong type of config for "+
"subserver %s, expected %T got %T", subServerName,
&Config{}, subServerConf)
}
return New(config)
}
func init() {
subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName,
NewGrpcHandler: func() lnrpc.GrpcHandler {
return &ServerShell{}
},
}
// If the build tag is active, then we'll register ourselves as a
// sub-RPC server within the global lnrpc package namespace.
if err := lnrpc.RegisterSubServer(subServer); err != nil {
panic(fmt.Sprintf("failed to register sub server driver "+
"'%s': %v", subServerName, err))
}
}
+32
View File
@@ -0,0 +1,32 @@
package peersrpc
import (
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var log btclog.Logger
// Subsystem defines the logging code for this subsystem.
const Subsystem = "PRPC"
// The default amount of logging is none.
func init() {
UseLogger(build.NewSubLogger(Subsystem, nil))
}
// DisableLog disables all library log output. Logging output is disabled by
// by default until UseLogger is called.
func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info. This
// should be used in preference to SetLogWriter if the caller is also using
// btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}
+554
View File
@@ -0,0 +1,554 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc v3.6.1
// source: peersrpc/peers.proto
package peersrpc
import (
lnrpc "github.com/lightningnetwork/lnd/lnrpc"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// UpdateAction is used to determine the kind of action we are referring to.
type UpdateAction int32
const (
// ADD indicates this is an "insertion" kind of action.
UpdateAction_ADD UpdateAction = 0
// REMOVE indicates this is a "deletion" kind of action.
UpdateAction_REMOVE UpdateAction = 1
)
// Enum value maps for UpdateAction.
var (
UpdateAction_name = map[int32]string{
0: "ADD",
1: "REMOVE",
}
UpdateAction_value = map[string]int32{
"ADD": 0,
"REMOVE": 1,
}
)
func (x UpdateAction) Enum() *UpdateAction {
p := new(UpdateAction)
*p = x
return p
}
func (x UpdateAction) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (UpdateAction) Descriptor() protoreflect.EnumDescriptor {
return file_peersrpc_peers_proto_enumTypes[0].Descriptor()
}
func (UpdateAction) Type() protoreflect.EnumType {
return &file_peersrpc_peers_proto_enumTypes[0]
}
func (x UpdateAction) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use UpdateAction.Descriptor instead.
func (UpdateAction) EnumDescriptor() ([]byte, []int) {
return file_peersrpc_peers_proto_rawDescGZIP(), []int{0}
}
type FeatureSet int32
const (
//
//SET_INIT identifies features that should be sent in an Init message to
//a remote peer.
FeatureSet_SET_INIT FeatureSet = 0
//
//SET_LEGACY_GLOBAL identifies features that should be set in the legacy
//GlobalFeatures field of an Init message, which maintains backwards
//compatibility with nodes that haven't implemented flat features.
FeatureSet_SET_LEGACY_GLOBAL FeatureSet = 1
//
//SET_NODE_ANN identifies features that should be advertised on node
//announcements.
FeatureSet_SET_NODE_ANN FeatureSet = 2
//
//SET_INVOICE identifies features that should be advertised on invoices
//generated by the daemon.
FeatureSet_SET_INVOICE FeatureSet = 3
//
//SET_INVOICE_AMP identifies the features that should be advertised on
//AMP invoices generated by the daemon.
FeatureSet_SET_INVOICE_AMP FeatureSet = 4
)
// Enum value maps for FeatureSet.
var (
FeatureSet_name = map[int32]string{
0: "SET_INIT",
1: "SET_LEGACY_GLOBAL",
2: "SET_NODE_ANN",
3: "SET_INVOICE",
4: "SET_INVOICE_AMP",
}
FeatureSet_value = map[string]int32{
"SET_INIT": 0,
"SET_LEGACY_GLOBAL": 1,
"SET_NODE_ANN": 2,
"SET_INVOICE": 3,
"SET_INVOICE_AMP": 4,
}
)
func (x FeatureSet) Enum() *FeatureSet {
p := new(FeatureSet)
*p = x
return p
}
func (x FeatureSet) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (FeatureSet) Descriptor() protoreflect.EnumDescriptor {
return file_peersrpc_peers_proto_enumTypes[1].Descriptor()
}
func (FeatureSet) Type() protoreflect.EnumType {
return &file_peersrpc_peers_proto_enumTypes[1]
}
func (x FeatureSet) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use FeatureSet.Descriptor instead.
func (FeatureSet) EnumDescriptor() ([]byte, []int) {
return file_peersrpc_peers_proto_rawDescGZIP(), []int{1}
}
type UpdateAddressAction struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Determines the kind of action.
Action UpdateAction `protobuf:"varint,1,opt,name=action,proto3,enum=peersrpc.UpdateAction" json:"action,omitempty"`
// The address used to apply the update action.
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
}
func (x *UpdateAddressAction) Reset() {
*x = UpdateAddressAction{}
if protoimpl.UnsafeEnabled {
mi := &file_peersrpc_peers_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UpdateAddressAction) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdateAddressAction) ProtoMessage() {}
func (x *UpdateAddressAction) ProtoReflect() protoreflect.Message {
mi := &file_peersrpc_peers_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdateAddressAction.ProtoReflect.Descriptor instead.
func (*UpdateAddressAction) Descriptor() ([]byte, []int) {
return file_peersrpc_peers_proto_rawDescGZIP(), []int{0}
}
func (x *UpdateAddressAction) GetAction() UpdateAction {
if x != nil {
return x.Action
}
return UpdateAction_ADD
}
func (x *UpdateAddressAction) GetAddress() string {
if x != nil {
return x.Address
}
return ""
}
type UpdateFeatureAction struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Determines the kind of action.
Action UpdateAction `protobuf:"varint,1,opt,name=action,proto3,enum=peersrpc.UpdateAction" json:"action,omitempty"`
// The feature bit used to apply the update action.
FeatureBit lnrpc.FeatureBit `protobuf:"varint,2,opt,name=feature_bit,json=featureBit,proto3,enum=lnrpc.FeatureBit" json:"feature_bit,omitempty"`
}
func (x *UpdateFeatureAction) Reset() {
*x = UpdateFeatureAction{}
if protoimpl.UnsafeEnabled {
mi := &file_peersrpc_peers_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UpdateFeatureAction) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdateFeatureAction) ProtoMessage() {}
func (x *UpdateFeatureAction) ProtoReflect() protoreflect.Message {
mi := &file_peersrpc_peers_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdateFeatureAction.ProtoReflect.Descriptor instead.
func (*UpdateFeatureAction) Descriptor() ([]byte, []int) {
return file_peersrpc_peers_proto_rawDescGZIP(), []int{1}
}
func (x *UpdateFeatureAction) GetAction() UpdateAction {
if x != nil {
return x.Action
}
return UpdateAction_ADD
}
func (x *UpdateFeatureAction) GetFeatureBit() lnrpc.FeatureBit {
if x != nil {
return x.FeatureBit
}
return lnrpc.FeatureBit_DATALOSS_PROTECT_REQ
}
type NodeAnnouncementUpdateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Set of changes for the features that the node supports.
FeatureUpdates []*UpdateFeatureAction `protobuf:"bytes,1,rep,name=feature_updates,json=featureUpdates,proto3" json:"feature_updates,omitempty"`
// Color is the node's color in hex code format.
Color string `protobuf:"bytes,2,opt,name=color,proto3" json:"color,omitempty"`
// Alias or nick name of the node.
Alias string `protobuf:"bytes,3,opt,name=alias,proto3" json:"alias,omitempty"`
// Set of changes for the node's known addresses.
AddressUpdates []*UpdateAddressAction `protobuf:"bytes,4,rep,name=address_updates,json=addressUpdates,proto3" json:"address_updates,omitempty"`
}
func (x *NodeAnnouncementUpdateRequest) Reset() {
*x = NodeAnnouncementUpdateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_peersrpc_peers_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *NodeAnnouncementUpdateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NodeAnnouncementUpdateRequest) ProtoMessage() {}
func (x *NodeAnnouncementUpdateRequest) ProtoReflect() protoreflect.Message {
mi := &file_peersrpc_peers_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use NodeAnnouncementUpdateRequest.ProtoReflect.Descriptor instead.
func (*NodeAnnouncementUpdateRequest) Descriptor() ([]byte, []int) {
return file_peersrpc_peers_proto_rawDescGZIP(), []int{2}
}
func (x *NodeAnnouncementUpdateRequest) GetFeatureUpdates() []*UpdateFeatureAction {
if x != nil {
return x.FeatureUpdates
}
return nil
}
func (x *NodeAnnouncementUpdateRequest) GetColor() string {
if x != nil {
return x.Color
}
return ""
}
func (x *NodeAnnouncementUpdateRequest) GetAlias() string {
if x != nil {
return x.Alias
}
return ""
}
func (x *NodeAnnouncementUpdateRequest) GetAddressUpdates() []*UpdateAddressAction {
if x != nil {
return x.AddressUpdates
}
return nil
}
type NodeAnnouncementUpdateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Ops []*lnrpc.Op `protobuf:"bytes,1,rep,name=ops,proto3" json:"ops,omitempty"`
}
func (x *NodeAnnouncementUpdateResponse) Reset() {
*x = NodeAnnouncementUpdateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_peersrpc_peers_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *NodeAnnouncementUpdateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NodeAnnouncementUpdateResponse) ProtoMessage() {}
func (x *NodeAnnouncementUpdateResponse) ProtoReflect() protoreflect.Message {
mi := &file_peersrpc_peers_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use NodeAnnouncementUpdateResponse.ProtoReflect.Descriptor instead.
func (*NodeAnnouncementUpdateResponse) Descriptor() ([]byte, []int) {
return file_peersrpc_peers_proto_rawDescGZIP(), []int{3}
}
func (x *NodeAnnouncementUpdateResponse) GetOps() []*lnrpc.Op {
if x != nil {
return x.Ops
}
return nil
}
var File_peersrpc_peers_proto protoreflect.FileDescriptor
var file_peersrpc_peers_proto_rawDesc = []byte{
0x0a, 0x14, 0x70, 0x65, 0x65, 0x72, 0x73, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x65, 0x65, 0x72, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x70, 0x65, 0x65, 0x72, 0x73, 0x72, 0x70, 0x63,
0x1a, 0x0f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x22, 0x5f, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x73,
0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x22, 0x79, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74,
0x75, 0x72, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x65, 0x65, 0x72,
0x73, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x0b, 0x66, 0x65, 0x61,
0x74, 0x75, 0x72, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11,
0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69,
0x74, 0x52, 0x0a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x22, 0xdb, 0x01,
0x0a, 0x1d, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x46, 0x0a, 0x0f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74,
0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x73,
0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72,
0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x14, 0x0a,
0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c,
0x69, 0x61, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70,
0x65, 0x65, 0x72, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x64,
0x64, 0x72, 0x65, 0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x61, 0x64, 0x64,
0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0x3d, 0x0a, 0x1e, 0x4e,
0x6f, 0x64, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a,
0x03, 0x6f, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6c, 0x6e, 0x72,
0x70, 0x63, 0x2e, 0x4f, 0x70, 0x52, 0x03, 0x6f, 0x70, 0x73, 0x2a, 0x23, 0x0a, 0x0c, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x44,
0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x01, 0x2a,
0x69, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x0c, 0x0a,
0x08, 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x53,
0x45, 0x54, 0x5f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c,
0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x41,
0x4e, 0x4e, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x56, 0x4f,
0x49, 0x43, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x56,
0x4f, 0x49, 0x43, 0x45, 0x5f, 0x41, 0x4d, 0x50, 0x10, 0x04, 0x32, 0x74, 0x0a, 0x05, 0x50, 0x65,
0x65, 0x72, 0x73, 0x12, 0x6b, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64,
0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x2e,
0x70, 0x65, 0x65, 0x72, 0x73, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x6e, 0x6e,
0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x73, 0x72, 0x70,
0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65,
0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c,
0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f,
0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x65, 0x65, 0x72, 0x73, 0x72,
0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_peersrpc_peers_proto_rawDescOnce sync.Once
file_peersrpc_peers_proto_rawDescData = file_peersrpc_peers_proto_rawDesc
)
func file_peersrpc_peers_proto_rawDescGZIP() []byte {
file_peersrpc_peers_proto_rawDescOnce.Do(func() {
file_peersrpc_peers_proto_rawDescData = protoimpl.X.CompressGZIP(file_peersrpc_peers_proto_rawDescData)
})
return file_peersrpc_peers_proto_rawDescData
}
var file_peersrpc_peers_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_peersrpc_peers_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_peersrpc_peers_proto_goTypes = []interface{}{
(UpdateAction)(0), // 0: peersrpc.UpdateAction
(FeatureSet)(0), // 1: peersrpc.FeatureSet
(*UpdateAddressAction)(nil), // 2: peersrpc.UpdateAddressAction
(*UpdateFeatureAction)(nil), // 3: peersrpc.UpdateFeatureAction
(*NodeAnnouncementUpdateRequest)(nil), // 4: peersrpc.NodeAnnouncementUpdateRequest
(*NodeAnnouncementUpdateResponse)(nil), // 5: peersrpc.NodeAnnouncementUpdateResponse
(lnrpc.FeatureBit)(0), // 6: lnrpc.FeatureBit
(*lnrpc.Op)(nil), // 7: lnrpc.Op
}
var file_peersrpc_peers_proto_depIdxs = []int32{
0, // 0: peersrpc.UpdateAddressAction.action:type_name -> peersrpc.UpdateAction
0, // 1: peersrpc.UpdateFeatureAction.action:type_name -> peersrpc.UpdateAction
6, // 2: peersrpc.UpdateFeatureAction.feature_bit:type_name -> lnrpc.FeatureBit
3, // 3: peersrpc.NodeAnnouncementUpdateRequest.feature_updates:type_name -> peersrpc.UpdateFeatureAction
2, // 4: peersrpc.NodeAnnouncementUpdateRequest.address_updates:type_name -> peersrpc.UpdateAddressAction
7, // 5: peersrpc.NodeAnnouncementUpdateResponse.ops:type_name -> lnrpc.Op
4, // 6: peersrpc.Peers.UpdateNodeAnnouncement:input_type -> peersrpc.NodeAnnouncementUpdateRequest
5, // 7: peersrpc.Peers.UpdateNodeAnnouncement:output_type -> peersrpc.NodeAnnouncementUpdateResponse
7, // [7:8] is the sub-list for method output_type
6, // [6:7] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_peersrpc_peers_proto_init() }
func file_peersrpc_peers_proto_init() {
if File_peersrpc_peers_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_peersrpc_peers_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateAddressAction); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_peersrpc_peers_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateFeatureAction); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_peersrpc_peers_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NodeAnnouncementUpdateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_peersrpc_peers_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NodeAnnouncementUpdateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_peersrpc_peers_proto_rawDesc,
NumEnums: 2,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_peersrpc_peers_proto_goTypes,
DependencyIndexes: file_peersrpc_peers_proto_depIdxs,
EnumInfos: file_peersrpc_peers_proto_enumTypes,
MessageInfos: file_peersrpc_peers_proto_msgTypes,
}.Build()
File_peersrpc_peers_proto = out.File
file_peersrpc_peers_proto_rawDesc = nil
file_peersrpc_peers_proto_goTypes = nil
file_peersrpc_peers_proto_depIdxs = nil
}
+167
View File
@@ -0,0 +1,167 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: peersrpc/peers.proto
/*
Package peersrpc is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package peersrpc
import (
"context"
"io"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = metadata.Join
func request_Peers_UpdateNodeAnnouncement_0(ctx context.Context, marshaler runtime.Marshaler, client PeersClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq NodeAnnouncementUpdateRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.UpdateNodeAnnouncement(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Peers_UpdateNodeAnnouncement_0(ctx context.Context, marshaler runtime.Marshaler, server PeersServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq NodeAnnouncementUpdateRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.UpdateNodeAnnouncement(ctx, &protoReq)
return msg, metadata, err
}
// RegisterPeersHandlerServer registers the http handlers for service Peers to "mux".
// UnaryRPC :call PeersServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterPeersHandlerFromEndpoint instead.
func RegisterPeersHandlerServer(ctx context.Context, mux *runtime.ServeMux, server PeersServer) error {
mux.Handle("POST", pattern_Peers_UpdateNodeAnnouncement_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/peersrpc.Peers/UpdateNodeAnnouncement", runtime.WithHTTPPathPattern("/v2/peers/nodeannouncement"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Peers_UpdateNodeAnnouncement_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Peers_UpdateNodeAnnouncement_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterPeersHandlerFromEndpoint is same as RegisterPeersHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterPeersHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterPeersHandler(ctx, mux, conn)
}
// RegisterPeersHandler registers the http handlers for service Peers to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterPeersHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterPeersHandlerClient(ctx, mux, NewPeersClient(conn))
}
// RegisterPeersHandlerClient registers the http handlers for service Peers
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "PeersClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "PeersClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "PeersClient" to call the correct interceptors.
func RegisterPeersHandlerClient(ctx context.Context, mux *runtime.ServeMux, client PeersClient) error {
mux.Handle("POST", pattern_Peers_UpdateNodeAnnouncement_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/peersrpc.Peers/UpdateNodeAnnouncement", runtime.WithHTTPPathPattern("/v2/peers/nodeannouncement"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Peers_UpdateNodeAnnouncement_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Peers_UpdateNodeAnnouncement_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_Peers_UpdateNodeAnnouncement_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v2", "peers", "nodeannouncement"}, ""))
)
var (
forward_Peers_UpdateNodeAnnouncement_0 = runtime.ForwardResponseMessage
)
+50
View File
@@ -0,0 +1,50 @@
// Code generated by falafel 0.9.1. DO NOT EDIT.
// source: peers.proto
// +build js
package peersrpc
import (
"context"
gateway "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
"google.golang.org/protobuf/encoding/protojson"
)
func RegisterPeersJSONCallbacks(registry map[string]func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error))) {
marshaler := &gateway.JSONPb{
MarshalOptions: protojson.MarshalOptions{
UseProtoNames: true,
EmitUnpopulated: true,
},
}
registry["peersrpc.Peers.UpdateNodeAnnouncement"] = func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
req := &NodeAnnouncementUpdateRequest{}
err := marshaler.Unmarshal([]byte(reqJSON), req)
if err != nil {
callback("", err)
return
}
client := NewPeersClient(conn)
resp, err := client.UpdateNodeAnnouncement(ctx, req)
if err != nil {
callback("", err)
return
}
respBytes, err := marshaler.Marshal(resp)
if err != nil {
callback("", err)
return
}
callback(string(respBytes), nil)
}
}
+94
View File
@@ -0,0 +1,94 @@
syntax = "proto3";
import "lightning.proto";
package peersrpc;
option go_package = "github.com/lightningnetwork/lnd/lnrpc/peersrpc";
// Peers is a service that can be used to get information and interact
// with the other nodes of the newtwork.
service Peers {
/* lncli: peers updatenodeannouncement
UpdateNodeAnnouncement allows the caller to update the node parameters
and broadcasts a new version of the node announcement to its peers.
*/
rpc UpdateNodeAnnouncement (NodeAnnouncementUpdateRequest)
returns (NodeAnnouncementUpdateResponse);
}
// UpdateAction is used to determine the kind of action we are referring to.
enum UpdateAction {
// ADD indicates this is an "insertion" kind of action.
ADD = 0;
// REMOVE indicates this is a "deletion" kind of action.
REMOVE = 1;
}
enum FeatureSet {
/*
SET_INIT identifies features that should be sent in an Init message to
a remote peer.
*/
SET_INIT = 0;
/*
SET_LEGACY_GLOBAL identifies features that should be set in the legacy
GlobalFeatures field of an Init message, which maintains backwards
compatibility with nodes that haven't implemented flat features.
*/
SET_LEGACY_GLOBAL = 1;
/*
SET_NODE_ANN identifies features that should be advertised on node
announcements.
*/
SET_NODE_ANN = 2;
/*
SET_INVOICE identifies features that should be advertised on invoices
generated by the daemon.
*/
SET_INVOICE = 3;
/*
SET_INVOICE_AMP identifies the features that should be advertised on
AMP invoices generated by the daemon.
*/
SET_INVOICE_AMP = 4;
}
message UpdateAddressAction {
// Determines the kind of action.
UpdateAction action = 1;
// The address used to apply the update action.
string address = 2;
}
message UpdateFeatureAction {
// Determines the kind of action.
UpdateAction action = 1;
// The feature bit used to apply the update action.
lnrpc.FeatureBit feature_bit = 2;
}
message NodeAnnouncementUpdateRequest {
// Set of changes for the features that the node supports.
repeated UpdateFeatureAction feature_updates = 1;
// Color is the node's color in hex code format.
string color = 2;
// Alias or nick name of the node.
string alias = 3;
// Set of changes for the node's known addresses.
repeated UpdateAddressAction address_updates = 4;
}
message NodeAnnouncementUpdateResponse {
repeated lnrpc.Op ops = 1;
}
+203
View File
@@ -0,0 +1,203 @@
{
"swagger": "2.0",
"info": {
"title": "peersrpc/peers.proto",
"version": "version not set"
},
"tags": [
{
"name": "Peers"
}
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/v2/peers/nodeannouncement": {
"post": {
"summary": "lncli: peers updatenodeannouncement\nUpdateNodeAnnouncement allows the caller to update the node parameters\nand broadcasts a new version of the node announcement to its peers.",
"operationId": "Peers_UpdateNodeAnnouncement",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/peersrpcNodeAnnouncementUpdateResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/peersrpcNodeAnnouncementUpdateRequest"
}
}
],
"tags": [
"Peers"
]
}
}
},
"definitions": {
"lnrpcFeatureBit": {
"type": "string",
"enum": [
"DATALOSS_PROTECT_REQ",
"DATALOSS_PROTECT_OPT",
"INITIAL_ROUING_SYNC",
"UPFRONT_SHUTDOWN_SCRIPT_REQ",
"UPFRONT_SHUTDOWN_SCRIPT_OPT",
"GOSSIP_QUERIES_REQ",
"GOSSIP_QUERIES_OPT",
"TLV_ONION_REQ",
"TLV_ONION_OPT",
"EXT_GOSSIP_QUERIES_REQ",
"EXT_GOSSIP_QUERIES_OPT",
"STATIC_REMOTE_KEY_REQ",
"STATIC_REMOTE_KEY_OPT",
"PAYMENT_ADDR_REQ",
"PAYMENT_ADDR_OPT",
"MPP_REQ",
"MPP_OPT",
"WUMBO_CHANNELS_REQ",
"WUMBO_CHANNELS_OPT",
"ANCHORS_REQ",
"ANCHORS_OPT",
"ANCHORS_ZERO_FEE_HTLC_REQ",
"ANCHORS_ZERO_FEE_HTLC_OPT",
"AMP_REQ",
"AMP_OPT"
],
"default": "DATALOSS_PROTECT_REQ"
},
"lnrpcOp": {
"type": "object",
"properties": {
"entity": {
"type": "string"
},
"actions": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"peersrpcNodeAnnouncementUpdateRequest": {
"type": "object",
"properties": {
"feature_updates": {
"type": "array",
"items": {
"$ref": "#/definitions/peersrpcUpdateFeatureAction"
},
"description": "Set of changes for the features that the node supports."
},
"color": {
"type": "string",
"description": "Color is the node's color in hex code format."
},
"alias": {
"type": "string",
"description": "Alias or nick name of the node."
},
"address_updates": {
"type": "array",
"items": {
"$ref": "#/definitions/peersrpcUpdateAddressAction"
},
"description": "Set of changes for the node's known addresses."
}
}
},
"peersrpcNodeAnnouncementUpdateResponse": {
"type": "object",
"properties": {
"ops": {
"type": "array",
"items": {
"$ref": "#/definitions/lnrpcOp"
}
}
}
},
"peersrpcUpdateAction": {
"type": "string",
"enum": [
"ADD",
"REMOVE"
],
"default": "ADD",
"description": "UpdateAction is used to determine the kind of action we are referring to.\n\n - ADD: ADD indicates this is an \"insertion\" kind of action.\n - REMOVE: REMOVE indicates this is a \"deletion\" kind of action."
},
"peersrpcUpdateAddressAction": {
"type": "object",
"properties": {
"action": {
"$ref": "#/definitions/peersrpcUpdateAction",
"description": "Determines the kind of action."
},
"address": {
"type": "string",
"description": "The address used to apply the update action."
}
}
},
"peersrpcUpdateFeatureAction": {
"type": "object",
"properties": {
"action": {
"$ref": "#/definitions/peersrpcUpdateAction",
"description": "Determines the kind of action."
},
"feature_bit": {
"$ref": "#/definitions/lnrpcFeatureBit",
"description": "The feature bit used to apply the update action."
}
}
},
"protobufAny": {
"type": "object",
"properties": {
"type_url": {
"type": "string"
},
"value": {
"type": "string",
"format": "byte"
}
}
},
"rpcStatus": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
},
"details": {
"type": "array",
"items": {
"$ref": "#/definitions/protobufAny"
}
}
}
}
}
}
+8
View File
@@ -0,0 +1,8 @@
type: google.api.Service
config_version: 3
http:
rules:
- selector: peersrpc.Peers.UpdateNodeAnnouncement
post: "/v2/peers/nodeannouncement"
body: "*"
+107
View File
@@ -0,0 +1,107 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package peersrpc
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// PeersClient is the client API for Peers service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PeersClient interface {
// lncli: peers updatenodeannouncement
//UpdateNodeAnnouncement allows the caller to update the node parameters
//and broadcasts a new version of the node announcement to its peers.
UpdateNodeAnnouncement(ctx context.Context, in *NodeAnnouncementUpdateRequest, opts ...grpc.CallOption) (*NodeAnnouncementUpdateResponse, error)
}
type peersClient struct {
cc grpc.ClientConnInterface
}
func NewPeersClient(cc grpc.ClientConnInterface) PeersClient {
return &peersClient{cc}
}
func (c *peersClient) UpdateNodeAnnouncement(ctx context.Context, in *NodeAnnouncementUpdateRequest, opts ...grpc.CallOption) (*NodeAnnouncementUpdateResponse, error) {
out := new(NodeAnnouncementUpdateResponse)
err := c.cc.Invoke(ctx, "/peersrpc.Peers/UpdateNodeAnnouncement", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// PeersServer is the server API for Peers service.
// All implementations must embed UnimplementedPeersServer
// for forward compatibility
type PeersServer interface {
// lncli: peers updatenodeannouncement
//UpdateNodeAnnouncement allows the caller to update the node parameters
//and broadcasts a new version of the node announcement to its peers.
UpdateNodeAnnouncement(context.Context, *NodeAnnouncementUpdateRequest) (*NodeAnnouncementUpdateResponse, error)
mustEmbedUnimplementedPeersServer()
}
// UnimplementedPeersServer must be embedded to have forward compatible implementations.
type UnimplementedPeersServer struct {
}
func (UnimplementedPeersServer) UpdateNodeAnnouncement(context.Context, *NodeAnnouncementUpdateRequest) (*NodeAnnouncementUpdateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateNodeAnnouncement not implemented")
}
func (UnimplementedPeersServer) mustEmbedUnimplementedPeersServer() {}
// UnsafePeersServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PeersServer will
// result in compilation errors.
type UnsafePeersServer interface {
mustEmbedUnimplementedPeersServer()
}
func RegisterPeersServer(s grpc.ServiceRegistrar, srv PeersServer) {
s.RegisterService(&Peers_ServiceDesc, srv)
}
func _Peers_UpdateNodeAnnouncement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(NodeAnnouncementUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PeersServer).UpdateNodeAnnouncement(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/peersrpc.Peers/UpdateNodeAnnouncement",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PeersServer).UpdateNodeAnnouncement(ctx, req.(*NodeAnnouncementUpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
// Peers_ServiceDesc is the grpc.ServiceDesc for Peers service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Peers_ServiceDesc = grpc.ServiceDesc{
ServiceName: "peersrpc.Peers",
HandlerType: (*PeersServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "UpdateNodeAnnouncement",
Handler: _Peers_UpdateNodeAnnouncement_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "peersrpc/peers.proto",
}
+403
View File
@@ -0,0 +1,403 @@
//go:build peersrpc
// +build peersrpc
package peersrpc
import (
"context"
"fmt"
"net"
"sync/atomic"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/lightningnetwork/lnd/feature"
"github.com/lightningnetwork/lnd/lncfg"
"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"
)
const (
// subServerName is the name of the sub rpc server. We'll use this name
// to register ourselves, and we also require that the main
// SubServerConfigDispatcher instance recognize tt as the name of our
// RPC service.
subServerName = "PeersRPC"
)
var (
// macPermissions maps RPC calls to the permissions they require.
macPermissions = map[string][]bakery.Op{
"/peersrpc.Peers/UpdateNodeAnnouncement": {{
Entity: "peers",
Action: "write",
}},
}
)
// ServerShell is a shell struct holding a reference to the actual sub-server.
// It is used to register the gRPC sub-server with the root server before we
// have the necessary dependencies to populate the actual sub-server.
type ServerShell struct {
PeersServer
}
// Server is a sub-server of the main RPC server: the peers RPC. This sub
// RPC server allows to intereact with our Peers in the Lightning Network.
type Server struct {
started int32 // To be used atomically.
shutdown int32 // To be used atomically.
// Required by the grpc-gateway/v2 library for forward compatibility.
// Must be after the atomically used variables to not break struct
// alignment.
UnimplementedPeersServer
cfg *Config
}
// A compile time check to ensure that Server fully implements the PeersServer
// gRPC service.
var _ PeersServer = (*Server)(nil)
// New returns a new instance of the peersrpc Peers sub-server. We also
// return the set of permissions for the macaroons that we may create within
// this method. If the macaroons we need aren't found in the filepath, then
// we'll create them on start up. If we're unable to locate, or create the
// macaroons we need, then we'll return with an error.
func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) {
server := &Server{
cfg: cfg,
}
return server, macPermissions, nil
}
// Start launches any helper goroutines required for the Server to function.
//
// NOTE: This is part of the lnrpc.SubServer interface.
func (s *Server) Start() error {
if atomic.AddInt32(&s.started, 1) != 1 {
return nil
}
return nil
}
// Stop signals any active goroutines for a graceful closure.
//
// NOTE: This is part of the lnrpc.SubServer interface.
func (s *Server) Stop() error {
if atomic.AddInt32(&s.shutdown, 1) != 1 {
return nil
}
return nil
}
// Name returns a unique string representation of the sub-server. This can be
// used to identify the sub-server and also de-duplicate them.
//
// NOTE: This is part of the lnrpc.SubServer interface.
func (s *Server) Name() string {
return subServerName
}
// RegisterWithRootServer will be called by the root gRPC server to direct a
// sub RPC server to register itself with the main gRPC root server. Until this
// is called, each sub-server won't be able to have
// requests routed towards it.
//
// NOTE: This is part of the lnrpc.GrpcHandler interface.
func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly.
RegisterPeersServer(grpcServer, r)
log.Debugf("Peers RPC server successfully register with root " +
"gRPC server")
return nil
}
// RegisterWithRestServer will be called by the root REST mux to direct a sub
// RPC server to register itself with the main REST mux server. Until this is
// called, each sub-server won't be able to have requests routed towards it.
//
// NOTE: This is part of the lnrpc.GrpcHandler interface.
func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure
// all our methods are routed properly.
err := RegisterPeersHandlerFromEndpoint(ctx, mux, dest, opts)
if err != nil {
log.Errorf("Could not register Peers REST server "+
"with root REST server: %v", err)
return err
}
log.Debugf("Peers REST server successfully registered with " +
"root REST server")
return nil
}
// CreateSubServer populates the subserver's dependencies using the passed
// SubServerConfigDispatcher. This method should fully initialize the
// sub-server instance, making it ready for action. It returns the macaroon
// permissions that the sub-server wishes to pass on to the root server for all
// methods routed towards it.
//
// NOTE: This is part of the lnrpc.GrpcHandler interface.
func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
subServer, macPermissions, err := createNewSubServer(configRegistry)
if err != nil {
return nil, nil, err
}
r.PeersServer = subServer
return subServer, macPermissions, nil
}
// updateAddresses computes the new address set after executing the update
// actions.
func (s *Server) updateAddresses(currentAddresses []net.Addr,
updates []*UpdateAddressAction) ([]net.Addr, *lnrpc.Op, error) {
// net.Addr is not comparable so we cannot use the default map
// (map[net.Addr]struct{}) so we have to use arrays and a helping
// function.
findAddr := func(addr net.Addr, slice []net.Addr) bool {
for _, sAddr := range slice {
if sAddr.Network() != addr.Network() {
continue
}
if sAddr.String() == addr.String() {
return true
}
}
return false
}
// Preallocate enough memory for both arrays.
removeAddr := make([]net.Addr, 0, len(updates))
addAddr := make([]net.Addr, 0, len(updates))
for _, update := range updates {
addr, err := s.cfg.ParseAddr(update.Address)
if err != nil {
return nil, nil, fmt.Errorf("unable to resolve "+
"address %v: %v", update.Address, err)
}
switch update.Action {
case UpdateAction_ADD:
addAddr = append(addAddr, addr)
case UpdateAction_REMOVE:
removeAddr = append(removeAddr, addr)
default:
return nil, nil, fmt.Errorf("invalid address update "+
"action: %v", update.Action)
}
}
// Look for any inconsistency trying to add AND remove the same address.
for _, addr := range removeAddr {
if findAddr(addr, addAddr) {
return nil, nil, fmt.Errorf("invalid updates for "+
"removing AND adding %v", addr)
}
}
ops := &lnrpc.Op{Entity: "addresses"}
newAddrs := make([]net.Addr, 0, len(updates)+len(currentAddresses))
// Copy current addresses excluding the ones that need to be removed.
for _, addr := range currentAddresses {
if findAddr(addr, removeAddr) {
ops.Actions = append(
ops.Actions,
fmt.Sprintf("%s removed", addr.String()),
)
continue
}
newAddrs = append(newAddrs, addr)
}
// Add new adresses if needed.
for _, addr := range addAddr {
if !findAddr(addr, newAddrs) {
ops.Actions = append(
ops.Actions,
fmt.Sprintf("%s added", addr.String()),
)
newAddrs = append(newAddrs, addr)
}
}
return newAddrs, ops, nil
}
// updateFeatures computes the new raw SetNodeAnn after executing the update
// actions.
func (s *Server) updateFeatures(currentfeatures *lnwire.RawFeatureVector,
updates []*UpdateFeatureAction) (*lnwire.RawFeatureVector,
*lnrpc.Op, error) {
ops := &lnrpc.Op{Entity: "features"}
raw := currentfeatures.Clone()
for _, update := range updates {
bit := lnwire.FeatureBit(update.FeatureBit)
switch update.Action {
case UpdateAction_ADD:
if raw.IsSet(bit) {
return nil, nil, fmt.Errorf(
"invalid add action for bit %v, "+
"bit is already set",
update.FeatureBit,
)
}
raw.Set(bit)
ops.Actions = append(
ops.Actions,
fmt.Sprintf("%s set", lnwire.Features[bit]),
)
case UpdateAction_REMOVE:
if !raw.IsSet(bit) {
return nil, nil, fmt.Errorf(
"invalid remove action for bit %v, "+
"bit is already unset",
update.FeatureBit,
)
}
raw.Unset(bit)
ops.Actions = append(
ops.Actions,
fmt.Sprintf("%s unset", lnwire.Features[bit]),
)
default:
return nil, nil, fmt.Errorf(
"invalid update action (%v) for bit %v",
update.Action,
update.FeatureBit,
)
}
}
// Validate our new SetNodeAnn.
fv := lnwire.NewFeatureVector(raw, lnwire.Features)
if err := feature.ValidateDeps(fv); err != nil {
return nil, nil, fmt.Errorf(
"invalid feature set (SetNodeAnn): %v",
err,
)
}
return raw, ops, nil
}
// UpdateNodeAnnouncement allows the caller to update the node parameters
// and broadcasts a new version of the node announcement to its peers.
func (s *Server) UpdateNodeAnnouncement(_ context.Context,
req *NodeAnnouncementUpdateRequest) (
*NodeAnnouncementUpdateResponse, error) {
resp := &NodeAnnouncementUpdateResponse{}
nodeModifiers := make([]netann.NodeAnnModifier, 0)
currentNodeAnn, err := s.cfg.GetNodeAnnouncement()
if err != nil {
return nil, fmt.Errorf("unable to get current node "+
"announcement: %v", err)
}
if len(req.FeatureUpdates) > 0 {
features, ops, err := s.updateFeatures(
currentNodeAnn.Features,
req.FeatureUpdates,
)
if err != nil {
return nil, fmt.Errorf("error trying to update node "+
"features: %w", err)
}
resp.Ops = append(resp.Ops, ops)
nodeModifiers = append(
nodeModifiers,
netann.NodeAnnSetFeatures(features),
)
}
if req.Color != "" {
color, err := lncfg.ParseHexColor(req.Color)
if err != nil {
return nil, fmt.Errorf("unable to parse color: %v", err)
}
if color != currentNodeAnn.RGBColor {
resp.Ops = append(resp.Ops, &lnrpc.Op{
Entity: "color",
Actions: []string{
fmt.Sprintf("changed to %v", color),
},
})
nodeModifiers = append(
nodeModifiers,
netann.NodeAnnSetColor(color),
)
}
}
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),
)
}
}
if len(req.AddressUpdates) > 0 {
newAddrs, ops, err := s.updateAddresses(
currentNodeAnn.Addresses,
req.AddressUpdates,
)
if err != nil {
return nil, fmt.Errorf("error trying to update node "+
"addresses: %w", err)
}
resp.Ops = append(resp.Ops, ops)
nodeModifiers = append(
nodeModifiers,
netann.NodeAnnSetAddrs(newAddrs),
)
}
if len(nodeModifiers) == 0 {
return nil, fmt.Errorf("unable detect any new values to " +
"update the node announcement")
}
if err := s.cfg.UpdateNodeAnnouncement(nodeModifiers...); err != nil {
return nil, err
}
return resp, nil
}
+1 -17
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger
@@ -30,19 +30,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) {
log = logger
}
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
+1 -17
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) {
log = logger
}
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger
+2 -18
View File
@@ -5,7 +5,7 @@ import (
"github.com/lightningnetwork/lnd/build"
)
// log is a logger that is initialized with no output filters. This means the
// log is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var log btclog.Logger
@@ -21,25 +21,9 @@ func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info. This
// UseLogger uses a specified Logger to output package logging info. This
// should be used in preference to SetLogWriter if the caller is also using
// btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
-16
View File
@@ -29,19 +29,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) {
log = logger
}
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
+4
View File
@@ -25,6 +25,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
@@ -356,6 +357,7 @@ type HarnessNode struct {
lnrpc.LightningClient
lnrpc.WalletUnlockerClient
invoicesrpc.InvoicesClient
peersrpc.PeersClient
SignerClient signrpc.SignerClient
RouterClient routerrpc.RouterClient
WalletKitClient walletrpc.WalletKitClient
@@ -387,6 +389,7 @@ type RPCClients struct {
var _ lnrpc.LightningClient = (*HarnessNode)(nil)
var _ lnrpc.WalletUnlockerClient = (*HarnessNode)(nil)
var _ invoicesrpc.InvoicesClient = (*HarnessNode)(nil)
var _ peersrpc.PeersClient = (*HarnessNode)(nil)
// nextNodeID generates a unique sequence to be used as the node's ID.
func nextNodeID() int {
@@ -952,6 +955,7 @@ func (hn *HarnessNode) initLightningClient() error {
hn.Watchtower = watchtowerrpc.NewWatchtowerClient(conn)
hn.WatchtowerClient = wtclientrpc.NewWatchtowerClientClient(conn)
hn.SignerClient = signrpc.NewSignerClient(conn)
hn.PeersClient = peersrpc.NewPeersClient(conn)
hn.StateClient = lnrpc.NewStateClient(conn)
hn.ChainClient = chainrpc.NewChainNotifierClient(conn)
+52
View File
@@ -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,54 @@ 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")
// Color should match.
require.Equal(t.t, n1.Color, n2.Color, "color don't match")
// NodeAddresses should match.
require.Equal(
t.t, len(n1.NodeAddresses), len(n2.NodeAddresses),
"node addresses don't match",
)
addrs := make(map[string]struct{}, len(n1.NodeAddresses))
for _, nodeAddr := range n1.NodeAddresses {
addrs[nodeAddr.Addr] = struct{}{}
}
for _, nodeAddr := range n2.NodeAddresses {
if _, ok := addrs[nodeAddr.Addr]; !ok {
t.Fatalf("address %v not found in node announcement",
nodeAddr.Addr)
}
}
}
// 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)
}
}
}
+262
View File
@@ -5,6 +5,7 @@ import (
"context"
"fmt"
"io"
"strings"
"testing"
"time"
@@ -12,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
@@ -767,3 +769,263 @@ func subscribeGraphNotifications(ctxb context.Context, t *harnessTest,
quit: quit,
}
}
// 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) {
// 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
// Add some exta addresses to the default ones.
extraAddrs := []string{
"192.168.1.1:8333",
"[2001:db8:85a3:8d3:1319:8a2e:370:7348]:8337",
"bkb6azqggsaiskzi.onion:9735",
"fomvuglh6h6vcag73xo5t5gv56ombih3zr2xvplkpbfd7wrog4swjwid.onion:1234",
}
for _, addr := range extraAddrs {
lndArgs = append(lndArgs, "--externalip="+addr)
}
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")
defaultAddrs := make([]*lnrpc.NodeAddress, 0, len(resp.Uris))
for _, uri := range resp.GetUris() {
values := strings.Split(uri, "@")
defaultAddrs = append(
defaultAddrs, &lnrpc.NodeAddress{
Addr: values[1],
Network: "tcp",
},
)
}
// This feature bit is used to test that our endpoint sets/unsets
// feature bits properly. If the current FeatureBit is set by default
// update this one for another one unset by default at random.
featureBit := lnrpc.FeatureBit_WUMBO_CHANNELS_REQ
featureIdx := uint32(featureBit)
if _, ok := resp.Features[featureIdx]; ok {
t.Fatalf("unexpected feature bit enabled by default")
}
defaultDaveNodeAnn := &lnrpc.NodeUpdate{
Alias: resp.Alias,
Color: resp.Color,
NodeAddresses: defaultAddrs,
}
// 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
// modifiers are applied.
invalidNodeAnnReq := &peersrpc.NodeAnnouncementUpdateRequest{
Alias: "",
}
_, 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"
newColor := "#2288ee"
newAddresses := []string{
"192.168.1.10:8333",
"192.168.1.11:8333",
}
updateAddressActions := []*peersrpc.UpdateAddressAction{
{
Action: peersrpc.UpdateAction_ADD,
Address: newAddresses[0],
},
{
Action: peersrpc.UpdateAction_ADD,
Address: newAddresses[1],
},
{
Action: peersrpc.UpdateAction_REMOVE,
Address: defaultAddrs[0].Addr,
},
}
updateFeatureActions := []*peersrpc.UpdateFeatureAction{
{
Action: peersrpc.UpdateAction_ADD,
FeatureBit: featureBit,
},
}
nodeAnnReq := &peersrpc.NodeAnnouncementUpdateRequest{
Alias: newAlias,
Color: newColor,
AddressUpdates: updateAddressActions,
FeatureUpdates: updateFeatureActions,
}
response, err := dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
require.NoError(t.t, err, "unable to update dave's node announcement")
expectedOps := map[string]int{
"features": 1,
"color": 1,
"alias": 1,
"addresses": 3,
}
assertUpdateNodeAnnouncementResponse(t, response, expectedOps)
newNodeAddresses := []*lnrpc.NodeAddress{}
// We removed the first address.
newNodeAddresses = append(newNodeAddresses, defaultAddrs[1:]...)
newNodeAddresses = append(
newNodeAddresses,
&lnrpc.NodeAddress{Addr: newAddresses[0], Network: "tcp"},
&lnrpc.NodeAddress{Addr: newAddresses[1], Network: "tcp"},
)
// 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,
Color: newColor,
NodeAddresses: newNodeAddresses,
}
// We'll then wait for Alice to receive dave's node announcement
// with the new values.
waitForNodeAnnUpdates(
aliceSub, dave.PubKeyStr, newDaveNodeAnn, t,
)
// Check that the feature bit was set correctly.
resp, err = dave.GetInfo(ctxt, nodeInfoReq)
require.NoError(t.t, err, "unable to get dave's information")
if _, ok := resp.Features[featureIdx]; !ok {
t.Fatalf("failed to set feature bit")
}
// Check that we cannot set a feature bit that is already set.
nodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
FeatureUpdates: updateFeatureActions,
}
_, err = dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
require.Error(
t.t, err, "missing expected error: cannot set a feature bit "+
"that is already set",
)
// Check that we can unset feature bits.
updateFeatureActions = []*peersrpc.UpdateFeatureAction{
{
Action: peersrpc.UpdateAction_REMOVE,
FeatureBit: featureBit,
},
}
nodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
FeatureUpdates: updateFeatureActions,
}
response, err = dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
require.NoError(t.t, err, "unable to update dave's node announcement")
expectedOps = map[string]int{
"features": 1,
}
assertUpdateNodeAnnouncementResponse(t, response, expectedOps)
resp, err = dave.GetInfo(ctxt, nodeInfoReq)
require.NoError(t.t, err, "unable to get dave's information")
if _, ok := resp.Features[featureIdx]; ok {
t.Fatalf("failed to unset feature bit")
}
// Check that we cannot unset a feature bit that is already unset.
nodeAnnReq = &peersrpc.NodeAnnouncementUpdateRequest{
FeatureUpdates: updateFeatureActions,
}
_, err = dave.UpdateNodeAnnouncement(ctxt, nodeAnnReq)
require.Error(
t.t, err, "missing expected error: cannot unset a feature bit "+
"that is already unset",
)
// Close the channel between Bob and Dave.
closeChannelAndAssert(t, net, net.Bob, chanPoint, false)
}
+4
View File
@@ -84,6 +84,10 @@ var allTestCases = []*testCase{
name: "update channel status",
test: testUpdateChanStatus,
},
{
name: "test update node announcement rpc",
test: testUpdateNodeAnnouncement,
},
{
name: "list outgoing payments",
test: testListPayments,
+2
View File
@@ -25,6 +25,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"github.com/lightningnetwork/lnd/lnrpc/devrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
@@ -168,6 +169,7 @@ func SetupLoggers(root *build.RotatingLogWriter, interceptor signal.Interceptor)
AddSubLogger(root, tor.Subsystem, interceptor, tor.UseLogger)
AddSubLogger(root, btcwallet.Subsystem, interceptor, btcwallet.UseLogger)
AddSubLogger(root, rpcwallet.Subsystem, interceptor, rpcwallet.UseLogger)
AddSubLogger(root, peersrpc.Subsystem, interceptor, peersrpc.UseLogger)
}
// AddSubLogger is a helper method to conveniently create and register the
+2 -2
View File
@@ -37,9 +37,9 @@ windows-386 \
windows-amd64 \
windows-arm
RELEASE_TAGS = autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc monitoring kvdb_postgres kvdb_etcd
RELEASE_TAGS = autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc monitoring peersrpc kvdb_postgres kvdb_etcd
WASM_RELEASE_TAGS = autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc monitoring
WASM_RELEASE_TAGS = autopilotrpc signrpc walletrpc chainrpc invoicesrpc watchtowerrpc monitoring peersrpc
# One can either specify a git tag as the version suffix or one is generated
# from the current date.
+1 -1
View File
@@ -1,5 +1,5 @@
DEV_TAGS = dev
RPC_TAGS = autopilotrpc chainrpc invoicesrpc routerrpc signrpc verrpc walletrpc watchtowerrpc wtclientrpc
RPC_TAGS = autopilotrpc chainrpc invoicesrpc peersrpc routerrpc signrpc verrpc walletrpc watchtowerrpc wtclientrpc
LOG_TAGS =
TEST_FLAGS =
ITEST_FLAGS =
+25
View File
@@ -1,6 +1,7 @@
package netann
import (
"image/color"
"net"
"time"
@@ -13,6 +14,14 @@ import (
// lnwire.NodeAnnouncement.
type NodeAnnModifier func(*lnwire.NodeAnnouncement)
// NodeAnnSetAlias is a functional option that sets the alias of the
// given node announcement.
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) {
@@ -21,6 +30,22 @@ func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement) {
}
}
// NodeAnnSetColor is a functional option that sets the color of the
// given node announcement.
func NodeAnnSetColor(newColor color.RGBA) func(*lnwire.NodeAnnouncement) {
return func(nodeAnn *lnwire.NodeAnnouncement) {
nodeAnn.RGBColor = newColor
}
}
// NodeAnnSetFeatures is a functional option that allows updating the features of
// the given node announcement.
func NodeAnnSetFeatures(features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement) {
return func(nodeAnn *lnwire.NodeAnnouncement) {
nodeAnn.Features = features
}
}
// NodeAnnSetTimestamp is a functional option that sets the timestamp of the
// announcement to the current time, or increments it if the timestamp is
// already in the future.
+11 -1
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"io"
"math"
"net"
"net/http"
"runtime"
"sort"
@@ -729,6 +730,14 @@ func (r *rpcServer) addDeps(s *server, macService *macaroons.Service,
return s.featureMgr.Get(feature.SetInvoiceAmp)
}
getNodeAnnouncement := func() (lnwire.NodeAnnouncement, error) {
return s.genNodeAnnouncement(false)
}
parseAddr := func(addr string) (net.Addr, error) {
return parseAddr(addr, r.cfg.net)
}
var (
subServers []lnrpc.SubServer
subServerPerms []lnrpc.MacaroonPerms
@@ -745,7 +754,8 @@ func (r *rpcServer) addDeps(s *server, macService *macaroons.Service,
routerBackend, s.nodeSigner, s.graphDB, s.chanStateDB,
s.sweeper, tower, s.towerClient, s.anchorTowerClient,
r.cfg.net.ResolveTCPAddr, genInvoiceFeatures,
genAmpInvoiceFeatures, rpcsLog,
genAmpInvoiceFeatures, getNodeAnnouncement,
s.updateAndBrodcastSelfNode, parseAddr, rpcsLog,
)
if err != nil {
return err
+53
View File
@@ -2734,6 +2734,59 @@ func (s *server) genNodeAnnouncement(refresh bool,
return *s.currentNodeAnn, nil
}
// updateAndBrodcastSelfNode generates a new node announcement
// applying the giving modifiers and updating the time stamp
// to ensure it propagates through the network. Then it brodcasts
// it to the network.
func (s *server) updateAndBrodcastSelfNode(
modifiers ...netann.NodeAnnModifier) error {
newNodeAnn, err := s.genNodeAnnouncement(true, modifiers...)
if err != nil {
return fmt.Errorf("unable to generate new node "+
"announcement: %v", err)
}
// Update the on-disk version of our announcement.
// Load and modify self node istead of creating anew instance so we
// don't risk overwriting any existing values.
selfNode, err := s.graphDB.SourceNode()
if err != nil {
return fmt.Errorf("unable to get current source node: %v", err)
}
selfNode.HaveNodeAnnouncement = true
selfNode.LastUpdate = time.Unix(int64(newNodeAnn.Timestamp), 0)
selfNode.Addresses = newNodeAnn.Addresses
selfNode.Alias = newNodeAnn.Alias.String()
selfNode.Features = lnwire.NewFeatureVector(
newNodeAnn.Features, lnwire.Features,
)
selfNode.Color = newNodeAnn.RGBColor
selfNode.AuthSigBytes = newNodeAnn.Signature.ToSignatureBytes()
copy(selfNode.PubKeyBytes[:], s.identityECDH.PubKey().SerializeCompressed())
if err := s.graphDB.SetSourceNode(selfNode); err != nil {
return fmt.Errorf("can't set self node: %v", err)
}
// Update the feature bits for the SetNodeAnn in case they changed.
s.featureMgr.SetRaw(
feature.SetNodeAnn, selfNode.Features.RawFeatureVector,
)
// Finally, propagate it to the nodes in the network.
err = s.BroadcastMessage(nil, &newNodeAnn)
if err != nil {
rpcsLog.Debugf("Unable to broadcast new node "+
"announcement to peers: %v", err)
return err
}
return nil
}
type nodeAddresses struct {
pubKey *btcec.PublicKey
addresses []net.Addr
+24
View File
@@ -2,6 +2,7 @@ package lnd
import (
"fmt"
"net"
"reflect"
"github.com/btcsuite/btcd/chaincfg"
@@ -16,6 +17,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"github.com/lightningnetwork/lnd/lnrpc/devrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
@@ -60,6 +62,10 @@ type subRPCServerConfigs struct {
// as a gRPC service.
InvoicesRPC *invoicesrpc.Config `group:"invoicesrpc" namespace:"invoicesrpc"`
// PeersRPC is a sub-RPC server that exposes peer related methods
// as a gRPC service.
PeersRPC *peersrpc.Config `group:"peersrpc" namespace:"peersrpc"`
// RouterRPC is a sub-RPC server the exposes functionality that allows
// clients to send payments on the network, and perform Lightning
// payment related queries such as requests for estimates of off-chain
@@ -107,6 +113,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
tcpResolver lncfg.TCPResolver,
genInvoiceFeatures func() *lnwire.FeatureVector,
genAmpInvoiceFeatures func() *lnwire.FeatureVector,
getNodeAnnouncement func() (lnwire.NodeAnnouncement, error),
updateNodeAnnouncement func(modifiers ...netann.NodeAnnModifier) error,
parseAddr func(addr string) (net.Addr, error),
rpcLogger btclog.Logger) error {
// First, we'll use reflect to obtain a version of the config struct
@@ -287,6 +296,21 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
reflect.ValueOf(graphDB),
)
case *peersrpc.Config:
subCfgValue := extractReflectValue(subCfg)
subCfgValue.FieldByName("GetNodeAnnouncement").Set(
reflect.ValueOf(getNodeAnnouncement),
)
subCfgValue.FieldByName("ParseAddr").Set(
reflect.ValueOf(parseAddr),
)
subCfgValue.FieldByName("UpdateNodeAnnouncement").Set(
reflect.ValueOf(updateNodeAnnouncement),
)
default:
return fmt.Errorf("unknown field: %v, %T", fieldName,
cfg)