Merge pull request #5587 from positiveblue/5466-update-node-announcement-data
lnrpc: Add UpdateNodeAnnouncement endpoint
This commit is contained in:
40 files changed
+2348
-112
No files matched your search
@@ -17,6 +17,7 @@ run:
|
||||
- chainrpc
|
||||
- dev
|
||||
- invoicesrpc
|
||||
- peersrpc
|
||||
- signrpc
|
||||
- walletrpc
|
||||
- watchtowerrpc
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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).
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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=""
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
//go:build !peersrpc
|
||||
// +build !peersrpc
|
||||
|
||||
package peersrpc
|
||||
|
||||
// Config is empty for non-peersrpc builds.
|
||||
type Config struct{}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
type: google.api.Service
|
||||
config_version: 3
|
||||
|
||||
http:
|
||||
rules:
|
||||
- selector: peersrpc.Peers.UpdateNodeAnnouncement
|
||||
post: "/v2/peers/nodeannouncement"
|
||||
body: "*"
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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 =
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user