multi: add watchtower client RPC subserver

This commit is contained in:
Wilmer Paulino 2019-06-07 17:46:31 -07:00
parent c57128097e
commit 8f010abac5
No known key found for this signature in database
GPG Key ID: 6DF57B9F9514972F
13 changed files with 1646 additions and 8 deletions

View File

@ -0,0 +1,27 @@
// +build wtclientrpc
package wtclientrpc
import (
"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/watchtower/wtclient"
)
// Config is the primary configuration struct for the watchtower RPC server. It
// contains all the items required for the RPC 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 {
// Active indicates if the watchtower client is enabled.
Active bool
// Client is the backing watchtower client that we'll interact with
// through the watchtower RPC subserver.
Client wtclient.Client
// Resolver is a custom resolver that will be used to resolve watchtower
// addresses to ensure we don't leak any information when running over
// non-clear networks, e.g. Tor, etc.
Resolver lncfg.TCPResolver
}

View File

@ -0,0 +1,6 @@
// +build !wtclientrpc
package wtclientrpc
// Config is empty for non-wtclientrpc builds.
type Config struct{}

View File

@ -0,0 +1,63 @@
// +build wtclientrpc
package wtclientrpc
import (
"errors"
"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) (
lnrpc.SubServer, 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)
}
// Before we try to make the new service instance, we'll perform
// some sanity checks on the arguments to ensure that they're useable.
switch {
case config.Resolver == nil:
return nil, nil, errors.New("a lncfg.TCPResolver is required")
}
return New(config)
}
func init() {
subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer,
lnrpc.MacaroonPerms, error) {
return createNewSubServer(c)
},
}
// 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))
}
}

48
lnrpc/wtclientrpc/log.go Normal file
View File

@ -0,0 +1,48 @@
package wtclientrpc
import (
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)
// Subsystem defines the logging code for this subsystem.
const Subsystem = "WTCL"
// 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
// 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
}
// 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
// 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 {
return logClosure(c)
}

View File

@ -0,0 +1,309 @@
// +build wtclientrpc
package wtclientrpc
import (
"context"
"errors"
"fmt"
"net"
"strconv"
"github.com/btcsuite/btcd/btcec"
"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/watchtower"
"github.com/lightningnetwork/lnd/watchtower/wtclient"
"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 recognizes it as the name of our
// RPC service.
subServerName = "WatchtowerClientRPC"
)
var (
// macPermissions maps RPC calls to the permissions they require.
//
// TODO(wilmer): create tower macaroon?
macPermissions = map[string][]bakery.Op{
"/wtclientrpc.WatchtowerClient/AddTower": {{
Entity: "offchain",
Action: "write",
}},
"/wtclientrpc.WatchtowerClient/RemoveTower": {{
Entity: "offchain",
Action: "write",
}},
"/wtclientrpc.WatchtowerClient/ListTowers": {{
Entity: "offchain",
Action: "read",
}},
"/wtclientrpc.WatchtowerClient/GetTowerInfo": {{
Entity: "offchain",
Action: "read",
}},
"/wtclientrpc.WatchtowerClient/Stats": {{
Entity: "offchain",
Action: "read",
}},
"/wtclientrpc.WatchtowerClient/Policy": {{
Entity: "offchain",
Action: "read",
}},
}
// ErrWtclientNotActive signals that RPC calls cannot be processed
// because the watchtower client is not active.
ErrWtclientNotActive = errors.New("watchtower client not active")
)
// WatchtowerClient is the RPC server we'll use to interact with the backing
// active watchtower client.
//
// TODO(wilmer): better name?
type WatchtowerClient struct {
cfg Config
}
// A compile time check to ensure that WatchtowerClient fully implements the
// WatchtowerClientWatchtowerClient gRPC service.
var _ WatchtowerClientServer = (*WatchtowerClient)(nil)
// New returns a new instance of the wtclientrpc WatchtowerClient 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) (*WatchtowerClient, lnrpc.MacaroonPerms, error) {
return &WatchtowerClient{*cfg}, macPermissions, nil
}
// Start launches any helper goroutines required for the WatchtowerClient to
// function.
//
// NOTE: This is part of the lnrpc.SubWatchtowerClient interface.
func (c *WatchtowerClient) Start() error {
return nil
}
// Stop signals any active goroutines for a graceful closure.
//
// NOTE: This is part of the lnrpc.SubServer interface.
func (c *WatchtowerClient) Stop() error {
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 (c *WatchtowerClient) 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.SubServer interface.
func (c *WatchtowerClient) 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.
RegisterWatchtowerClientServer(grpcServer, c)
log.Debugf("WatchtowerClient RPC server successfully registered with " +
"root gRPC server")
return nil
}
// isActive returns nil if the watchtower client is initialized so that we can
// process RPC requests.
func (c *WatchtowerClient) isActive() error {
if c.cfg.Active {
return nil
}
return ErrWtclientNotActive
}
// AddTower adds a new watchtower reachable at the given address and considers
// it for new sessions. If the watchtower already exists, then any new addresses
// included will be considered when dialing it for session negotiations and
// backups.
func (c *WatchtowerClient) AddTower(ctx context.Context,
req *AddTowerRequest) (*AddTowerResponse, error) {
if err := c.isActive(); err != nil {
return nil, err
}
pubKey, err := btcec.ParsePubKey(req.Pubkey, btcec.S256())
if err != nil {
return nil, err
}
addr, err := lncfg.ParseAddressString(
req.Address, strconv.Itoa(watchtower.DefaultPeerPort),
c.cfg.Resolver,
)
if err != nil {
return nil, fmt.Errorf("invalid address %v: %v", req.Address, err)
}
towerAddr := &lnwire.NetAddress{
IdentityKey: pubKey,
Address: addr,
}
if err := c.cfg.Client.AddTower(towerAddr); err != nil {
return nil, err
}
return &AddTowerResponse{}, nil
}
// RemoveTower removes a watchtower from being considered for future session
// negotiations and from being used for any subsequent backups until it's added
// again. If an address is provided, then this RPC only serves as a way of
// removing the address from the watchtower instead.
func (c *WatchtowerClient) RemoveTower(ctx context.Context,
req *RemoveTowerRequest) (*RemoveTowerResponse, error) {
if err := c.isActive(); err != nil {
return nil, err
}
pubKey, err := btcec.ParsePubKey(req.Pubkey, btcec.S256())
if err != nil {
return nil, err
}
var addr net.Addr
if req.Address != "" {
addr, err = lncfg.ParseAddressString(
req.Address, strconv.Itoa(watchtower.DefaultPeerPort),
c.cfg.Resolver,
)
if err != nil {
return nil, fmt.Errorf("unable to parse tower "+
"address %v: %v", req.Address, err)
}
}
if err := c.cfg.Client.RemoveTower(pubKey, addr); err != nil {
return nil, err
}
return &RemoveTowerResponse{}, nil
}
// ListTowers returns the list of watchtowers registered with the client.
func (c *WatchtowerClient) ListTowers(ctx context.Context,
req *ListTowersRequest) (*ListTowersResponse, error) {
if err := c.isActive(); err != nil {
return nil, err
}
towers, err := c.cfg.Client.RegisteredTowers()
if err != nil {
return nil, err
}
rpcTowers := make([]*Tower, 0, len(towers))
for _, tower := range towers {
rpcTower := marshallTower(tower, req.IncludeSessions)
rpcTowers = append(rpcTowers, rpcTower)
}
return &ListTowersResponse{Towers: rpcTowers}, nil
}
// GetTowerInfo retrieves information for a registered watchtower.
func (c *WatchtowerClient) GetTowerInfo(ctx context.Context,
req *GetTowerInfoRequest) (*Tower, error) {
if err := c.isActive(); err != nil {
return nil, err
}
pubKey, err := btcec.ParsePubKey(req.Pubkey, btcec.S256())
if err != nil {
return nil, err
}
tower, err := c.cfg.Client.LookupTower(pubKey)
if err != nil {
return nil, err
}
return marshallTower(tower, req.IncludeSessions), nil
}
// Stats returns the in-memory statistics of the client since startup.
func (c *WatchtowerClient) Stats(ctx context.Context,
req *StatsRequest) (*StatsResponse, error) {
if err := c.isActive(); err != nil {
return nil, err
}
stats := c.cfg.Client.Stats()
return &StatsResponse{
NumBackups: uint32(stats.NumTasksAccepted),
NumFailedBackups: uint32(stats.NumTasksIneligible),
NumPendingBackups: uint32(stats.NumTasksReceived),
NumSessionsAcquired: uint32(stats.NumSessionsAcquired),
NumSessionsExhausted: uint32(stats.NumSessionsExhausted),
}, nil
}
// Policy returns the active watchtower client policy configuration.
func (c *WatchtowerClient) Policy(ctx context.Context,
req *PolicyRequest) (*PolicyResponse, error) {
if err := c.isActive(); err != nil {
return nil, err
}
policy := c.cfg.Client.Policy()
return &PolicyResponse{
MaxUpdates: uint32(policy.MaxUpdates),
SweepSatPerByte: uint32(policy.SweepFeeRate.FeePerKVByte() / 1000),
}, nil
}
// marshallTower converts a client registered watchtower into its corresponding
// RPC type.
func marshallTower(tower *wtclient.RegisteredTower, includeSessions bool) *Tower {
rpcAddrs := make([]string, 0, len(tower.Addresses))
for _, addr := range tower.Addresses {
rpcAddrs = append(rpcAddrs, addr.String())
}
var rpcSessions []*TowerSession
if includeSessions {
rpcSessions = make([]*TowerSession, 0, len(tower.Sessions))
for _, session := range tower.Sessions {
satPerByte := session.Policy.SweepFeeRate.FeePerKVByte() / 1000
rpcSessions = append(rpcSessions, &TowerSession{
NumBackups: uint32(len(session.AckedUpdates)),
NumPendingBackups: uint32(len(session.CommittedUpdates)),
MaxBackups: uint32(session.Policy.MaxUpdates),
SweepSatPerByte: uint32(satPerByte),
})
}
}
return &Tower{
Pubkey: tower.IdentityKey.SerializeCompressed(),
Addresses: rpcAddrs,
ActiveSessionCandidate: tower.ActiveSessionCandidate,
NumSessions: uint32(len(tower.Sessions)),
Sessions: rpcSessions,
}
}

View File

@ -0,0 +1,988 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: wtclientrpc/wtclient.proto
package wtclientrpc
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type AddTowerRequest struct {
// The identifying public key of the watchtower to add.
Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
// A network address the watchtower is reachable over.
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AddTowerRequest) Reset() { *m = AddTowerRequest{} }
func (m *AddTowerRequest) String() string { return proto.CompactTextString(m) }
func (*AddTowerRequest) ProtoMessage() {}
func (*AddTowerRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{0}
}
func (m *AddTowerRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AddTowerRequest.Unmarshal(m, b)
}
func (m *AddTowerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AddTowerRequest.Marshal(b, m, deterministic)
}
func (m *AddTowerRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_AddTowerRequest.Merge(m, src)
}
func (m *AddTowerRequest) XXX_Size() int {
return xxx_messageInfo_AddTowerRequest.Size(m)
}
func (m *AddTowerRequest) XXX_DiscardUnknown() {
xxx_messageInfo_AddTowerRequest.DiscardUnknown(m)
}
var xxx_messageInfo_AddTowerRequest proto.InternalMessageInfo
func (m *AddTowerRequest) GetPubkey() []byte {
if m != nil {
return m.Pubkey
}
return nil
}
func (m *AddTowerRequest) GetAddress() string {
if m != nil {
return m.Address
}
return ""
}
type AddTowerResponse struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AddTowerResponse) Reset() { *m = AddTowerResponse{} }
func (m *AddTowerResponse) String() string { return proto.CompactTextString(m) }
func (*AddTowerResponse) ProtoMessage() {}
func (*AddTowerResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{1}
}
func (m *AddTowerResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AddTowerResponse.Unmarshal(m, b)
}
func (m *AddTowerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AddTowerResponse.Marshal(b, m, deterministic)
}
func (m *AddTowerResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_AddTowerResponse.Merge(m, src)
}
func (m *AddTowerResponse) XXX_Size() int {
return xxx_messageInfo_AddTowerResponse.Size(m)
}
func (m *AddTowerResponse) XXX_DiscardUnknown() {
xxx_messageInfo_AddTowerResponse.DiscardUnknown(m)
}
var xxx_messageInfo_AddTowerResponse proto.InternalMessageInfo
type RemoveTowerRequest struct {
// The identifying public key of the watchtower to remove.
Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
//
//If set, then the record for this address will be removed, indicating that is
//is stale. Otherwise, the watchtower will no longer be used for future
//session negotiations and backups.
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RemoveTowerRequest) Reset() { *m = RemoveTowerRequest{} }
func (m *RemoveTowerRequest) String() string { return proto.CompactTextString(m) }
func (*RemoveTowerRequest) ProtoMessage() {}
func (*RemoveTowerRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{2}
}
func (m *RemoveTowerRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RemoveTowerRequest.Unmarshal(m, b)
}
func (m *RemoveTowerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RemoveTowerRequest.Marshal(b, m, deterministic)
}
func (m *RemoveTowerRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_RemoveTowerRequest.Merge(m, src)
}
func (m *RemoveTowerRequest) XXX_Size() int {
return xxx_messageInfo_RemoveTowerRequest.Size(m)
}
func (m *RemoveTowerRequest) XXX_DiscardUnknown() {
xxx_messageInfo_RemoveTowerRequest.DiscardUnknown(m)
}
var xxx_messageInfo_RemoveTowerRequest proto.InternalMessageInfo
func (m *RemoveTowerRequest) GetPubkey() []byte {
if m != nil {
return m.Pubkey
}
return nil
}
func (m *RemoveTowerRequest) GetAddress() string {
if m != nil {
return m.Address
}
return ""
}
type RemoveTowerResponse struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RemoveTowerResponse) Reset() { *m = RemoveTowerResponse{} }
func (m *RemoveTowerResponse) String() string { return proto.CompactTextString(m) }
func (*RemoveTowerResponse) ProtoMessage() {}
func (*RemoveTowerResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{3}
}
func (m *RemoveTowerResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RemoveTowerResponse.Unmarshal(m, b)
}
func (m *RemoveTowerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RemoveTowerResponse.Marshal(b, m, deterministic)
}
func (m *RemoveTowerResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_RemoveTowerResponse.Merge(m, src)
}
func (m *RemoveTowerResponse) XXX_Size() int {
return xxx_messageInfo_RemoveTowerResponse.Size(m)
}
func (m *RemoveTowerResponse) XXX_DiscardUnknown() {
xxx_messageInfo_RemoveTowerResponse.DiscardUnknown(m)
}
var xxx_messageInfo_RemoveTowerResponse proto.InternalMessageInfo
type GetTowerInfoRequest struct {
// The identifying public key of the watchtower to retrieve information for.
Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
// Whether we should include sessions with the watchtower in the response.
IncludeSessions bool `protobuf:"varint,2,opt,name=include_sessions,proto3" json:"include_sessions,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetTowerInfoRequest) Reset() { *m = GetTowerInfoRequest{} }
func (m *GetTowerInfoRequest) String() string { return proto.CompactTextString(m) }
func (*GetTowerInfoRequest) ProtoMessage() {}
func (*GetTowerInfoRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{4}
}
func (m *GetTowerInfoRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetTowerInfoRequest.Unmarshal(m, b)
}
func (m *GetTowerInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetTowerInfoRequest.Marshal(b, m, deterministic)
}
func (m *GetTowerInfoRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetTowerInfoRequest.Merge(m, src)
}
func (m *GetTowerInfoRequest) XXX_Size() int {
return xxx_messageInfo_GetTowerInfoRequest.Size(m)
}
func (m *GetTowerInfoRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetTowerInfoRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetTowerInfoRequest proto.InternalMessageInfo
func (m *GetTowerInfoRequest) GetPubkey() []byte {
if m != nil {
return m.Pubkey
}
return nil
}
func (m *GetTowerInfoRequest) GetIncludeSessions() bool {
if m != nil {
return m.IncludeSessions
}
return false
}
type TowerSession struct {
//
//The total number of successful backups that have been made to the
//watchtower session.
NumBackups uint32 `protobuf:"varint,1,opt,name=num_backups,proto3" json:"num_backups,omitempty"`
//
//The total number of backups in the session that are currently pending to be
//acknowledged by the watchtower.
NumPendingBackups uint32 `protobuf:"varint,2,opt,name=num_pending_backups,proto3" json:"num_pending_backups,omitempty"`
// The maximum number of backups allowed by the watchtower session.
MaxBackups uint32 `protobuf:"varint,3,opt,name=max_backups,proto3" json:"max_backups,omitempty"`
//
//The fee rate, in satoshis per vbyte, that will be used by the watchtower for
//the justice transaction in the event of a channel breach.
SweepSatPerByte uint32 `protobuf:"varint,4,opt,name=sweep_sat_per_byte,proto3" json:"sweep_sat_per_byte,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *TowerSession) Reset() { *m = TowerSession{} }
func (m *TowerSession) String() string { return proto.CompactTextString(m) }
func (*TowerSession) ProtoMessage() {}
func (*TowerSession) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{5}
}
func (m *TowerSession) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_TowerSession.Unmarshal(m, b)
}
func (m *TowerSession) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_TowerSession.Marshal(b, m, deterministic)
}
func (m *TowerSession) XXX_Merge(src proto.Message) {
xxx_messageInfo_TowerSession.Merge(m, src)
}
func (m *TowerSession) XXX_Size() int {
return xxx_messageInfo_TowerSession.Size(m)
}
func (m *TowerSession) XXX_DiscardUnknown() {
xxx_messageInfo_TowerSession.DiscardUnknown(m)
}
var xxx_messageInfo_TowerSession proto.InternalMessageInfo
func (m *TowerSession) GetNumBackups() uint32 {
if m != nil {
return m.NumBackups
}
return 0
}
func (m *TowerSession) GetNumPendingBackups() uint32 {
if m != nil {
return m.NumPendingBackups
}
return 0
}
func (m *TowerSession) GetMaxBackups() uint32 {
if m != nil {
return m.MaxBackups
}
return 0
}
func (m *TowerSession) GetSweepSatPerByte() uint32 {
if m != nil {
return m.SweepSatPerByte
}
return 0
}
type Tower struct {
// The identifying public key of the watchtower.
Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
// The list of addresses the watchtower is reachable over.
Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"`
// Whether the watchtower is currently a candidate for new sessions.
ActiveSessionCandidate bool `protobuf:"varint,3,opt,name=active_session_candidate,proto3" json:"active_session_candidate,omitempty"`
// The number of sessions that have been negotiated with the watchtower.
NumSessions uint32 `protobuf:"varint,4,opt,name=num_sessions,proto3" json:"num_sessions,omitempty"`
// The list of sessions that have been negotiated with the watchtower.
Sessions []*TowerSession `protobuf:"bytes,5,rep,name=sessions,proto3" json:"sessions,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Tower) Reset() { *m = Tower{} }
func (m *Tower) String() string { return proto.CompactTextString(m) }
func (*Tower) ProtoMessage() {}
func (*Tower) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{6}
}
func (m *Tower) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Tower.Unmarshal(m, b)
}
func (m *Tower) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Tower.Marshal(b, m, deterministic)
}
func (m *Tower) XXX_Merge(src proto.Message) {
xxx_messageInfo_Tower.Merge(m, src)
}
func (m *Tower) XXX_Size() int {
return xxx_messageInfo_Tower.Size(m)
}
func (m *Tower) XXX_DiscardUnknown() {
xxx_messageInfo_Tower.DiscardUnknown(m)
}
var xxx_messageInfo_Tower proto.InternalMessageInfo
func (m *Tower) GetPubkey() []byte {
if m != nil {
return m.Pubkey
}
return nil
}
func (m *Tower) GetAddresses() []string {
if m != nil {
return m.Addresses
}
return nil
}
func (m *Tower) GetActiveSessionCandidate() bool {
if m != nil {
return m.ActiveSessionCandidate
}
return false
}
func (m *Tower) GetNumSessions() uint32 {
if m != nil {
return m.NumSessions
}
return 0
}
func (m *Tower) GetSessions() []*TowerSession {
if m != nil {
return m.Sessions
}
return nil
}
type ListTowersRequest struct {
// Whether we should include sessions with the watchtower in the response.
IncludeSessions bool `protobuf:"varint,1,opt,name=include_sessions,proto3" json:"include_sessions,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListTowersRequest) Reset() { *m = ListTowersRequest{} }
func (m *ListTowersRequest) String() string { return proto.CompactTextString(m) }
func (*ListTowersRequest) ProtoMessage() {}
func (*ListTowersRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{7}
}
func (m *ListTowersRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListTowersRequest.Unmarshal(m, b)
}
func (m *ListTowersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListTowersRequest.Marshal(b, m, deterministic)
}
func (m *ListTowersRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListTowersRequest.Merge(m, src)
}
func (m *ListTowersRequest) XXX_Size() int {
return xxx_messageInfo_ListTowersRequest.Size(m)
}
func (m *ListTowersRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ListTowersRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ListTowersRequest proto.InternalMessageInfo
func (m *ListTowersRequest) GetIncludeSessions() bool {
if m != nil {
return m.IncludeSessions
}
return false
}
type ListTowersResponse struct {
// The list of watchtowers available for new backups.
Towers []*Tower `protobuf:"bytes,1,rep,name=towers,proto3" json:"towers,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListTowersResponse) Reset() { *m = ListTowersResponse{} }
func (m *ListTowersResponse) String() string { return proto.CompactTextString(m) }
func (*ListTowersResponse) ProtoMessage() {}
func (*ListTowersResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{8}
}
func (m *ListTowersResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListTowersResponse.Unmarshal(m, b)
}
func (m *ListTowersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListTowersResponse.Marshal(b, m, deterministic)
}
func (m *ListTowersResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListTowersResponse.Merge(m, src)
}
func (m *ListTowersResponse) XXX_Size() int {
return xxx_messageInfo_ListTowersResponse.Size(m)
}
func (m *ListTowersResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ListTowersResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ListTowersResponse proto.InternalMessageInfo
func (m *ListTowersResponse) GetTowers() []*Tower {
if m != nil {
return m.Towers
}
return nil
}
type StatsRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StatsRequest) Reset() { *m = StatsRequest{} }
func (m *StatsRequest) String() string { return proto.CompactTextString(m) }
func (*StatsRequest) ProtoMessage() {}
func (*StatsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{9}
}
func (m *StatsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatsRequest.Unmarshal(m, b)
}
func (m *StatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StatsRequest.Marshal(b, m, deterministic)
}
func (m *StatsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_StatsRequest.Merge(m, src)
}
func (m *StatsRequest) XXX_Size() int {
return xxx_messageInfo_StatsRequest.Size(m)
}
func (m *StatsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_StatsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_StatsRequest proto.InternalMessageInfo
type StatsResponse struct {
//
//The total number of backups made to all active and exhausted watchtower
//sessions.
NumBackups uint32 `protobuf:"varint,1,opt,name=num_backups,proto3" json:"num_backups,omitempty"`
//
//The total number of backups that are pending to be acknowledged by all
//active and exhausted watchtower sessions.
NumPendingBackups uint32 `protobuf:"varint,2,opt,name=num_pending_backups,proto3" json:"num_pending_backups,omitempty"`
//
//The total number of backups that all active and exhausted watchtower
//sessions have failed to acknowledge.
NumFailedBackups uint32 `protobuf:"varint,3,opt,name=num_failed_backups,proto3" json:"num_failed_backups,omitempty"`
// The total number of new sessions made to watchtowers.
NumSessionsAcquired uint32 `protobuf:"varint,4,opt,name=num_sessions_acquired,proto3" json:"num_sessions_acquired,omitempty"`
// The total number of watchtower sessions that have been exhausted.
NumSessionsExhausted uint32 `protobuf:"varint,5,opt,name=num_sessions_exhausted,proto3" json:"num_sessions_exhausted,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StatsResponse) Reset() { *m = StatsResponse{} }
func (m *StatsResponse) String() string { return proto.CompactTextString(m) }
func (*StatsResponse) ProtoMessage() {}
func (*StatsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{10}
}
func (m *StatsResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatsResponse.Unmarshal(m, b)
}
func (m *StatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StatsResponse.Marshal(b, m, deterministic)
}
func (m *StatsResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_StatsResponse.Merge(m, src)
}
func (m *StatsResponse) XXX_Size() int {
return xxx_messageInfo_StatsResponse.Size(m)
}
func (m *StatsResponse) XXX_DiscardUnknown() {
xxx_messageInfo_StatsResponse.DiscardUnknown(m)
}
var xxx_messageInfo_StatsResponse proto.InternalMessageInfo
func (m *StatsResponse) GetNumBackups() uint32 {
if m != nil {
return m.NumBackups
}
return 0
}
func (m *StatsResponse) GetNumPendingBackups() uint32 {
if m != nil {
return m.NumPendingBackups
}
return 0
}
func (m *StatsResponse) GetNumFailedBackups() uint32 {
if m != nil {
return m.NumFailedBackups
}
return 0
}
func (m *StatsResponse) GetNumSessionsAcquired() uint32 {
if m != nil {
return m.NumSessionsAcquired
}
return 0
}
func (m *StatsResponse) GetNumSessionsExhausted() uint32 {
if m != nil {
return m.NumSessionsExhausted
}
return 0
}
type PolicyRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PolicyRequest) Reset() { *m = PolicyRequest{} }
func (m *PolicyRequest) String() string { return proto.CompactTextString(m) }
func (*PolicyRequest) ProtoMessage() {}
func (*PolicyRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{11}
}
func (m *PolicyRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PolicyRequest.Unmarshal(m, b)
}
func (m *PolicyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PolicyRequest.Marshal(b, m, deterministic)
}
func (m *PolicyRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_PolicyRequest.Merge(m, src)
}
func (m *PolicyRequest) XXX_Size() int {
return xxx_messageInfo_PolicyRequest.Size(m)
}
func (m *PolicyRequest) XXX_DiscardUnknown() {
xxx_messageInfo_PolicyRequest.DiscardUnknown(m)
}
var xxx_messageInfo_PolicyRequest proto.InternalMessageInfo
type PolicyResponse struct {
//
//The maximum number of updates each session we negotiate with watchtowers
//should allow.
MaxUpdates uint32 `protobuf:"varint,1,opt,name=max_updates,proto3" json:"max_updates,omitempty"`
//
//The fee rate, in satoshis per vbyte, that will be used by watchtowers for
//justice transactions in response to channel breaches.
SweepSatPerByte uint32 `protobuf:"varint,2,opt,name=sweep_sat_per_byte,proto3" json:"sweep_sat_per_byte,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PolicyResponse) Reset() { *m = PolicyResponse{} }
func (m *PolicyResponse) String() string { return proto.CompactTextString(m) }
func (*PolicyResponse) ProtoMessage() {}
func (*PolicyResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_b5f4e7d95a641af2, []int{12}
}
func (m *PolicyResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PolicyResponse.Unmarshal(m, b)
}
func (m *PolicyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PolicyResponse.Marshal(b, m, deterministic)
}
func (m *PolicyResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_PolicyResponse.Merge(m, src)
}
func (m *PolicyResponse) XXX_Size() int {
return xxx_messageInfo_PolicyResponse.Size(m)
}
func (m *PolicyResponse) XXX_DiscardUnknown() {
xxx_messageInfo_PolicyResponse.DiscardUnknown(m)
}
var xxx_messageInfo_PolicyResponse proto.InternalMessageInfo
func (m *PolicyResponse) GetMaxUpdates() uint32 {
if m != nil {
return m.MaxUpdates
}
return 0
}
func (m *PolicyResponse) GetSweepSatPerByte() uint32 {
if m != nil {
return m.SweepSatPerByte
}
return 0
}
func init() {
proto.RegisterType((*AddTowerRequest)(nil), "wtclientrpc.AddTowerRequest")
proto.RegisterType((*AddTowerResponse)(nil), "wtclientrpc.AddTowerResponse")
proto.RegisterType((*RemoveTowerRequest)(nil), "wtclientrpc.RemoveTowerRequest")
proto.RegisterType((*RemoveTowerResponse)(nil), "wtclientrpc.RemoveTowerResponse")
proto.RegisterType((*GetTowerInfoRequest)(nil), "wtclientrpc.GetTowerInfoRequest")
proto.RegisterType((*TowerSession)(nil), "wtclientrpc.TowerSession")
proto.RegisterType((*Tower)(nil), "wtclientrpc.Tower")
proto.RegisterType((*ListTowersRequest)(nil), "wtclientrpc.ListTowersRequest")
proto.RegisterType((*ListTowersResponse)(nil), "wtclientrpc.ListTowersResponse")
proto.RegisterType((*StatsRequest)(nil), "wtclientrpc.StatsRequest")
proto.RegisterType((*StatsResponse)(nil), "wtclientrpc.StatsResponse")
proto.RegisterType((*PolicyRequest)(nil), "wtclientrpc.PolicyRequest")
proto.RegisterType((*PolicyResponse)(nil), "wtclientrpc.PolicyResponse")
}
func init() { proto.RegisterFile("wtclientrpc/wtclient.proto", fileDescriptor_b5f4e7d95a641af2) }
var fileDescriptor_b5f4e7d95a641af2 = []byte{
// 634 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xcb, 0x6e, 0xd3, 0x40,
0x14, 0x95, 0x13, 0x12, 0xd2, 0x9b, 0xf4, 0xc1, 0xad, 0x5a, 0x19, 0x53, 0x68, 0xe4, 0x55, 0xd4,
0x45, 0x02, 0x2d, 0xb0, 0x60, 0x01, 0x94, 0x22, 0x2a, 0x24, 0x90, 0x2a, 0x17, 0x09, 0xc1, 0xc6,
0xf2, 0x63, 0x9a, 0x8c, 0xea, 0x8c, 0x5d, 0xcf, 0xb8, 0x69, 0x97, 0xfc, 0x13, 0xbf, 0xc0, 0x1f,
0xf0, 0x41, 0xc8, 0xe3, 0x47, 0xc6, 0x8d, 0x2d, 0x16, 0x88, 0x5d, 0xe6, 0x9c, 0x93, 0x33, 0x37,
0xf7, 0x9e, 0xdc, 0x01, 0x63, 0x21, 0xbc, 0x80, 0x12, 0x26, 0xe2, 0xc8, 0x9b, 0x14, 0x9f, 0xc7,
0x51, 0x1c, 0x8a, 0x10, 0xfb, 0x0a, 0x67, 0x9e, 0xc0, 0xe6, 0xb1, 0xef, 0x7f, 0x09, 0x17, 0x24,
0xb6, 0xc8, 0x55, 0x42, 0xb8, 0xc0, 0x5d, 0xe8, 0x46, 0x89, 0x7b, 0x49, 0x6e, 0x75, 0x6d, 0xa8,
0x8d, 0x06, 0x56, 0x7e, 0x42, 0x1d, 0xee, 0x3b, 0xbe, 0x1f, 0x13, 0xce, 0xf5, 0xd6, 0x50, 0x1b,
0xad, 0x59, 0xc5, 0xd1, 0x44, 0xd8, 0x5a, 0x9a, 0xf0, 0x28, 0x64, 0x9c, 0x98, 0x1f, 0x00, 0x2d,
0x32, 0x0f, 0xaf, 0xc9, 0x3f, 0x7a, 0xef, 0xc0, 0x76, 0xc5, 0x27, 0xb7, 0xff, 0x06, 0xdb, 0xa7,
0x44, 0x48, 0xec, 0x23, 0xbb, 0x08, 0xff, 0xe6, 0x7f, 0x00, 0x5b, 0x94, 0x79, 0x41, 0xe2, 0x13,
0x9b, 0x13, 0xce, 0x69, 0xc8, 0xb2, 0x8b, 0x7a, 0xd6, 0x0a, 0x6e, 0xfe, 0xd4, 0x60, 0x20, 0x8d,
0xcf, 0x33, 0x04, 0x87, 0xd0, 0x67, 0xc9, 0xdc, 0x76, 0x1d, 0xef, 0x32, 0x89, 0xb8, 0x74, 0x5e,
0xb7, 0x54, 0x08, 0x9f, 0xc2, 0x76, 0x7a, 0x8c, 0x08, 0xf3, 0x29, 0x9b, 0x96, 0xca, 0x96, 0x54,
0xd6, 0x51, 0xa9, 0xe7, 0xdc, 0xb9, 0x29, 0x95, 0xed, 0xcc, 0x53, 0x81, 0x70, 0x0c, 0xc8, 0x17,
0x84, 0x44, 0x36, 0x77, 0x84, 0x1d, 0x91, 0xd8, 0x76, 0x6f, 0x05, 0xd1, 0xef, 0x49, 0x61, 0x0d,
0x63, 0xfe, 0xd6, 0xa0, 0x23, 0xcb, 0x6e, 0x6c, 0xc2, 0x1e, 0xac, 0xe5, 0x5d, 0x25, 0x69, 0x6d,
0xed, 0xd1, 0x9a, 0xb5, 0x04, 0xf0, 0x15, 0xe8, 0x8e, 0x27, 0xe8, 0x75, 0xd9, 0x09, 0xdb, 0x73,
0x98, 0x4f, 0x7d, 0x47, 0x10, 0x59, 0x5e, 0xcf, 0x6a, 0xe4, 0xd1, 0x84, 0x41, 0xfa, 0x23, 0xcb,
0xd6, 0x66, 0x55, 0x56, 0x30, 0x7c, 0x01, 0xbd, 0x92, 0xef, 0x0c, 0xdb, 0xa3, 0xfe, 0xe1, 0xc3,
0xb1, 0x92, 0xc4, 0xb1, 0xda, 0x72, 0xab, 0x94, 0x9a, 0x6f, 0xe0, 0xc1, 0x27, 0xca, 0xb3, 0x49,
0xf3, 0x62, 0xcc, 0x75, 0xe3, 0xd4, 0x1a, 0xc6, 0xf9, 0x16, 0x50, 0x35, 0xc8, 0xf2, 0x83, 0x07,
0xd0, 0x15, 0x12, 0xd1, 0x35, 0x59, 0x0b, 0xae, 0xd6, 0x62, 0xe5, 0x0a, 0x73, 0x03, 0x06, 0xe7,
0xc2, 0x11, 0xc5, 0xed, 0xe6, 0x8f, 0x16, 0xac, 0xe7, 0x40, 0xee, 0xf6, 0x3f, 0x12, 0x32, 0x06,
0x4c, 0xe1, 0x0b, 0x87, 0x06, 0xc4, 0xbf, 0x13, 0x94, 0x1a, 0x06, 0x9f, 0xc3, 0x8e, 0xda, 0x6f,
0xdb, 0xf1, 0xae, 0x12, 0x1a, 0x13, 0x3f, 0x1f, 0x46, 0x3d, 0x89, 0x2f, 0x61, 0xb7, 0x42, 0x90,
0x9b, 0x99, 0x93, 0x70, 0x41, 0x7c, 0xbd, 0x23, 0xbf, 0xd6, 0xc0, 0x9a, 0x9b, 0xb0, 0x7e, 0x16,
0x06, 0xd4, 0xbb, 0x2d, 0x9a, 0xe2, 0xc2, 0x46, 0x01, 0x2c, 0x9b, 0x92, 0xe6, 0x39, 0x89, 0xd2,
0x88, 0x94, 0x4d, 0x51, 0xa0, 0x86, 0x88, 0xb7, 0x9a, 0x22, 0x7e, 0xf8, 0xab, 0x0d, 0x5b, 0x5f,
0x1d, 0xe1, 0xcd, 0xe4, 0x60, 0x4e, 0xe4, 0xb8, 0xf0, 0x14, 0x7a, 0xc5, 0xf2, 0xc1, 0xbd, 0xca,
0x14, 0xef, 0x2c, 0x36, 0xe3, 0x71, 0x03, 0x9b, 0xd7, 0x7b, 0x06, 0x7d, 0x65, 0xd3, 0xe0, 0x7e,
0x45, 0xbd, 0xba, 0xcb, 0x8c, 0x61, 0xb3, 0x20, 0x77, 0xfc, 0x0c, 0xb0, 0x8c, 0x1e, 0x3e, 0xa9,
0xe8, 0x57, 0x42, 0x6d, 0xec, 0x37, 0xf2, 0xb9, 0xdd, 0x7b, 0x18, 0xa8, 0x3b, 0x0f, 0xab, 0x05,
0xd4, 0xac, 0x43, 0xa3, 0x26, 0xd5, 0xf8, 0x1a, 0x3a, 0x32, 0xbc, 0x58, 0xfd, 0xfb, 0xa9, 0x09,
0x37, 0x8c, 0x3a, 0x2a, 0xaf, 0xe2, 0x18, 0xba, 0xd9, 0xa0, 0xb1, 0xaa, 0xaa, 0xc4, 0xc1, 0x78,
0x54, 0xcb, 0x65, 0x16, 0xef, 0x8e, 0xbe, 0x3f, 0x9b, 0x52, 0x31, 0x4b, 0xdc, 0xb1, 0x17, 0xce,
0x27, 0x01, 0x9d, 0xce, 0x04, 0xa3, 0x6c, 0xca, 0x88, 0x58, 0x84, 0xf1, 0xe5, 0x24, 0x60, 0xfe,
0x24, 0x60, 0xea, 0xcb, 0x15, 0x47, 0x9e, 0xdb, 0x95, 0xaf, 0xd7, 0xd1, 0x9f, 0x00, 0x00, 0x00,
0xff, 0xff, 0xdd, 0x33, 0x97, 0x54, 0xdb, 0x06, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// WatchtowerClientClient is the client API for WatchtowerClient service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type WatchtowerClientClient interface {
//
//AddTower adds a new watchtower reachable at the given address and
//considers it for new sessions. If the watchtower already exists, then
//any new addresses included will be considered when dialing it for
//session negotiations and backups.
AddTower(ctx context.Context, in *AddTowerRequest, opts ...grpc.CallOption) (*AddTowerResponse, error)
//
//RemoveTower removes a watchtower from being considered for future session
//negotiations and from being used for any subsequent backups until it's added
//again. If an address is provided, then this RPC only serves as a way of
//removing the address from the watchtower instead.
RemoveTower(ctx context.Context, in *RemoveTowerRequest, opts ...grpc.CallOption) (*RemoveTowerResponse, error)
// ListTowers returns the list of watchtowers registered with the client.
ListTowers(ctx context.Context, in *ListTowersRequest, opts ...grpc.CallOption) (*ListTowersResponse, error)
// GetTowerInfo retrieves information for a registered watchtower.
GetTowerInfo(ctx context.Context, in *GetTowerInfoRequest, opts ...grpc.CallOption) (*Tower, error)
// Stats returns the in-memory statistics of the client since startup.
Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error)
// Policy returns the active watchtower client policy configuration.
Policy(ctx context.Context, in *PolicyRequest, opts ...grpc.CallOption) (*PolicyResponse, error)
}
type watchtowerClientClient struct {
cc *grpc.ClientConn
}
func NewWatchtowerClientClient(cc *grpc.ClientConn) WatchtowerClientClient {
return &watchtowerClientClient{cc}
}
func (c *watchtowerClientClient) AddTower(ctx context.Context, in *AddTowerRequest, opts ...grpc.CallOption) (*AddTowerResponse, error) {
out := new(AddTowerResponse)
err := c.cc.Invoke(ctx, "/wtclientrpc.WatchtowerClient/AddTower", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *watchtowerClientClient) RemoveTower(ctx context.Context, in *RemoveTowerRequest, opts ...grpc.CallOption) (*RemoveTowerResponse, error) {
out := new(RemoveTowerResponse)
err := c.cc.Invoke(ctx, "/wtclientrpc.WatchtowerClient/RemoveTower", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *watchtowerClientClient) ListTowers(ctx context.Context, in *ListTowersRequest, opts ...grpc.CallOption) (*ListTowersResponse, error) {
out := new(ListTowersResponse)
err := c.cc.Invoke(ctx, "/wtclientrpc.WatchtowerClient/ListTowers", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *watchtowerClientClient) GetTowerInfo(ctx context.Context, in *GetTowerInfoRequest, opts ...grpc.CallOption) (*Tower, error) {
out := new(Tower)
err := c.cc.Invoke(ctx, "/wtclientrpc.WatchtowerClient/GetTowerInfo", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *watchtowerClientClient) Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) {
out := new(StatsResponse)
err := c.cc.Invoke(ctx, "/wtclientrpc.WatchtowerClient/Stats", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *watchtowerClientClient) Policy(ctx context.Context, in *PolicyRequest, opts ...grpc.CallOption) (*PolicyResponse, error) {
out := new(PolicyResponse)
err := c.cc.Invoke(ctx, "/wtclientrpc.WatchtowerClient/Policy", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// WatchtowerClientServer is the server API for WatchtowerClient service.
type WatchtowerClientServer interface {
//
//AddTower adds a new watchtower reachable at the given address and
//considers it for new sessions. If the watchtower already exists, then
//any new addresses included will be considered when dialing it for
//session negotiations and backups.
AddTower(context.Context, *AddTowerRequest) (*AddTowerResponse, error)
//
//RemoveTower removes a watchtower from being considered for future session
//negotiations and from being used for any subsequent backups until it's added
//again. If an address is provided, then this RPC only serves as a way of
//removing the address from the watchtower instead.
RemoveTower(context.Context, *RemoveTowerRequest) (*RemoveTowerResponse, error)
// ListTowers returns the list of watchtowers registered with the client.
ListTowers(context.Context, *ListTowersRequest) (*ListTowersResponse, error)
// GetTowerInfo retrieves information for a registered watchtower.
GetTowerInfo(context.Context, *GetTowerInfoRequest) (*Tower, error)
// Stats returns the in-memory statistics of the client since startup.
Stats(context.Context, *StatsRequest) (*StatsResponse, error)
// Policy returns the active watchtower client policy configuration.
Policy(context.Context, *PolicyRequest) (*PolicyResponse, error)
}
func RegisterWatchtowerClientServer(s *grpc.Server, srv WatchtowerClientServer) {
s.RegisterService(&_WatchtowerClient_serviceDesc, srv)
}
func _WatchtowerClient_AddTower_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddTowerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WatchtowerClientServer).AddTower(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/wtclientrpc.WatchtowerClient/AddTower",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WatchtowerClientServer).AddTower(ctx, req.(*AddTowerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WatchtowerClient_RemoveTower_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RemoveTowerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WatchtowerClientServer).RemoveTower(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/wtclientrpc.WatchtowerClient/RemoveTower",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WatchtowerClientServer).RemoveTower(ctx, req.(*RemoveTowerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WatchtowerClient_ListTowers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListTowersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WatchtowerClientServer).ListTowers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/wtclientrpc.WatchtowerClient/ListTowers",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WatchtowerClientServer).ListTowers(ctx, req.(*ListTowersRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WatchtowerClient_GetTowerInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetTowerInfoRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WatchtowerClientServer).GetTowerInfo(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/wtclientrpc.WatchtowerClient/GetTowerInfo",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WatchtowerClientServer).GetTowerInfo(ctx, req.(*GetTowerInfoRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WatchtowerClient_Stats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StatsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WatchtowerClientServer).Stats(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/wtclientrpc.WatchtowerClient/Stats",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WatchtowerClientServer).Stats(ctx, req.(*StatsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _WatchtowerClient_Policy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PolicyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(WatchtowerClientServer).Policy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/wtclientrpc.WatchtowerClient/Policy",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(WatchtowerClientServer).Policy(ctx, req.(*PolicyRequest))
}
return interceptor(ctx, in, info, handler)
}
var _WatchtowerClient_serviceDesc = grpc.ServiceDesc{
ServiceName: "wtclientrpc.WatchtowerClient",
HandlerType: (*WatchtowerClientServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "AddTower",
Handler: _WatchtowerClient_AddTower_Handler,
},
{
MethodName: "RemoveTower",
Handler: _WatchtowerClient_RemoveTower_Handler,
},
{
MethodName: "ListTowers",
Handler: _WatchtowerClient_ListTowers_Handler,
},
{
MethodName: "GetTowerInfo",
Handler: _WatchtowerClient_GetTowerInfo_Handler,
},
{
MethodName: "Stats",
Handler: _WatchtowerClient_Stats_Handler,
},
{
MethodName: "Policy",
Handler: _WatchtowerClient_Policy_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "wtclientrpc/wtclient.proto",
}

View File

@ -0,0 +1,165 @@
syntax = "proto3";
package wtclientrpc;
option go_package = "github.com/lightningnetwork/lnd/lnrpc/wtclientrpc";
message AddTowerRequest {
// The identifying public key of the watchtower to add.
bytes pubkey = 1 [json_name = "pubkey"];
// A network address the watchtower is reachable over.
string address = 2 [json_name = "address"];
}
message AddTowerResponse {
}
message RemoveTowerRequest {
// The identifying public key of the watchtower to remove.
bytes pubkey = 1 [json_name = "pubkey"];
/*
If set, then the record for this address will be removed, indicating that is
is stale. Otherwise, the watchtower will no longer be used for future
session negotiations and backups.
*/
string address = 2 [json_name = "address"];
}
message RemoveTowerResponse {
}
message GetTowerInfoRequest {
// The identifying public key of the watchtower to retrieve information for.
bytes pubkey = 1 [json_name = "pubkey"];
// Whether we should include sessions with the watchtower in the response.
bool include_sessions = 2 [json_name = "include_sessions"];
}
message TowerSession {
/*
The total number of successful backups that have been made to the
watchtower session.
*/
uint32 num_backups = 1 [json_name = "num_backups"];
/*
The total number of backups in the session that are currently pending to be
acknowledged by the watchtower.
*/
uint32 num_pending_backups = 2 [json_name = "num_pending_backups"];
// The maximum number of backups allowed by the watchtower session.
uint32 max_backups = 3 [json_name = "max_backups"];
/*
The fee rate, in satoshis per vbyte, that will be used by the watchtower for
the justice transaction in the event of a channel breach.
*/
uint32 sweep_sat_per_byte = 4 [json_name = "sweep_sat_per_byte"];
}
message Tower {
// The identifying public key of the watchtower.
bytes pubkey = 1 [json_name = "pubkey"];
// The list of addresses the watchtower is reachable over.
repeated string addresses = 2 [json_name = "addresses"];
// Whether the watchtower is currently a candidate for new sessions.
bool active_session_candidate = 3 [json_name = "active_session_candidate"];
// The number of sessions that have been negotiated with the watchtower.
uint32 num_sessions = 4 [json_name = "num_sessions"];
// The list of sessions that have been negotiated with the watchtower.
repeated TowerSession sessions = 5 [json_name = "sessions"];
}
message ListTowersRequest {
// Whether we should include sessions with the watchtower in the response.
bool include_sessions = 1 [json_name = "include_sessions"];
}
message ListTowersResponse {
// The list of watchtowers available for new backups.
repeated Tower towers = 1 [json_name = "towers"];
}
message StatsRequest {
}
message StatsResponse {
/*
The total number of backups made to all active and exhausted watchtower
sessions.
*/
uint32 num_backups = 1 [json_name = "num_backups"];
/*
The total number of backups that are pending to be acknowledged by all
active and exhausted watchtower sessions.
*/
uint32 num_pending_backups = 2 [json_name = "num_pending_backups"];
/*
The total number of backups that all active and exhausted watchtower
sessions have failed to acknowledge.
*/
uint32 num_failed_backups = 3 [json_name = "num_failed_backups"];
// The total number of new sessions made to watchtowers.
uint32 num_sessions_acquired = 4 [json_name = "num_sessions_acquired"];
// The total number of watchtower sessions that have been exhausted.
uint32 num_sessions_exhausted = 5 [json_name = "num_sessions_exhausted"];
}
message PolicyRequest {
}
message PolicyResponse {
/*
The maximum number of updates each session we negotiate with watchtowers
should allow.
*/
uint32 max_updates = 1 [json_name = "max_updates"];
/*
The fee rate, in satoshis per vbyte, that will be used by watchtowers for
justice transactions in response to channel breaches.
*/
uint32 sweep_sat_per_byte = 2 [json_name = "sweep_sat_per_byte"];
}
service WatchtowerClient {
/*
AddTower adds a new watchtower reachable at the given address and
considers it for new sessions. If the watchtower already exists, then
any new addresses included will be considered when dialing it for
session negotiations and backups.
*/
rpc AddTower(AddTowerRequest) returns (AddTowerResponse);
/*
RemoveTower removes a watchtower from being considered for future session
negotiations and from being used for any subsequent backups until it's added
again. If an address is provided, then this RPC only serves as a way of
removing the address from the watchtower instead.
*/
rpc RemoveTower(RemoveTowerRequest) returns (RemoveTowerResponse);
// ListTowers returns the list of watchtowers registered with the client.
rpc ListTowers(ListTowersRequest) returns (ListTowersResponse);
// GetTowerInfo retrieves information for a registered watchtower.
rpc GetTowerInfo(GetTowerInfoRequest) returns (Tower);
// Stats returns the in-memory statistics of the client since startup.
rpc Stats(StatsRequest) returns (StatsResponse);
// Policy returns the active watchtower client policy configuration.
rpc Policy(PolicyRequest) returns (PolicyResponse);
}

View File

@ -7677,7 +7677,7 @@ func testRevokedCloseRetributionAltruistWatchtower(net *lntest.NetworkHarness,
defer shutdownAndAssert(net, t, willy)
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
willyInfo, err := willy.WatchtowerClient.GetInfo(
willyInfo, err := willy.Watchtower.GetInfo(
ctxt, &watchtowerrpc.GetInfoRequest{},
)
if err != nil {

View File

@ -26,11 +26,12 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
"github.com/lightningnetwork/lnd/macaroons"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
macaroon "gopkg.in/macaroon.v2"
"gopkg.in/macaroon.v2"
)
const (
@ -265,7 +266,8 @@ type HarnessNode struct {
// because a name collision would occur with LightningClient.
RouterClient routerrpc.RouterClient
WalletKitClient walletrpc.WalletKitClient
WatchtowerClient watchtowerrpc.WatchtowerClient
Watchtower watchtowerrpc.WatchtowerClient
WatchtowerClient wtclientrpc.WatchtowerClientClient
}
// Assert *HarnessNode implements the lnrpc.LightningClient interface.
@ -526,7 +528,8 @@ func (hn *HarnessNode) initLightningClient(conn *grpc.ClientConn) error {
hn.InvoicesClient = invoicesrpc.NewInvoicesClient(conn)
hn.RouterClient = routerrpc.NewRouterClient(conn)
hn.WalletKitClient = walletrpc.NewWalletKitClient(conn)
hn.WatchtowerClient = watchtowerrpc.NewWatchtowerClient(conn)
hn.Watchtower = watchtowerrpc.NewWatchtowerClient(conn)
hn.WatchtowerClient = wtclientrpc.NewWatchtowerClientClient(conn)
// Set the harness node's pubkey to what the node claims in GetInfo.
err := hn.FetchNodeInfo()
@ -729,6 +732,7 @@ func (hn *HarnessNode) stop() error {
hn.processExit = nil
hn.LightningClient = nil
hn.WalletUnlockerClient = nil
hn.Watchtower = nil
hn.WatchtowerClient = nil
return nil
}

2
log.go
View File

@ -27,6 +27,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/monitoring"
"github.com/lightningnetwork/lnd/netann"
@ -120,6 +121,7 @@ func init() {
wtclient.UseLogger(wtclLog)
addSubLogger(routerrpc.Subsystem, routerrpc.UseLogger)
addSubLogger(wtclientrpc.Subsystem, wtclientrpc.UseLogger)
}
// addSubLogger is a helper method to conveniently register the logger of a sub

View File

@ -56,7 +56,7 @@ endif
# Construct the integration test command with the added build flags.
ITEST_TAGS := $(DEV_TAGS) rpctest chainrpc walletrpc signrpc invoicesrpc autopilotrpc routerrpc watchtowerrpc
ITEST_TAGS := $(DEV_TAGS) rpctest chainrpc walletrpc signrpc invoicesrpc autopilotrpc routerrpc watchtowerrpc wtclientrpc
# Default to btcd backend if not set.
ifneq ($(backend),)

View File

@ -497,8 +497,8 @@ func newRPCServer(s *server, macService *macaroons.Service,
err = subServerCgs.PopulateDependencies(
s.cc, networkDir, macService, atpl, invoiceRegistry,
s.htlcSwitch, activeNetParams.Params, s.chanRouter,
routerBackend, s.nodeSigner, s.chanDB, s.sweeper,
tower,
routerBackend, s.nodeSigner, s.chanDB, s.sweeper, tower,
s.towerClient, cfg.net.ResolveTCPAddr,
)
if err != nil {
return nil, err

View File

@ -9,6 +9,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc/autopilotrpc"
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
@ -16,11 +17,13 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/netann"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/sweep"
"github.com/lightningnetwork/lnd/watchtower"
"github.com/lightningnetwork/lnd/watchtower/wtclient"
)
// subRPCServerConfigs is special sub-config in the main configuration that
@ -62,6 +65,12 @@ type subRPCServerConfigs struct {
// WatchtowerRPC is a sub-RPC server that exposes functionality allowing
// clients to monitor and control their embedded watchtower.
WatchtowerRPC *watchtowerrpc.Config `group:"watchtowerrpc" namespace:"watchtowerrpc"`
// WatchtowerClientRPC is a sub-RPC server that exposes functionality
// that allows clients to interact with the active watchtower client
// instance within lnd in order to add, remove, list registered client
// towers, etc.
WatchtowerClientRPC *wtclientrpc.Config `group:"wtclientrpc" namespace:"wtclientrpc"`
}
// PopulateDependencies attempts to iterate through all the sub-server configs
@ -81,7 +90,9 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
nodeSigner *netann.NodeSigner,
chanDB *channeldb.DB,
sweeper *sweep.UtxoSweeper,
tower *watchtower.Standalone) error {
tower *watchtower.Standalone,
towerClient wtclient.Client,
tcpResolver lncfg.TCPResolver) error {
// First, we'll use reflect to obtain a version of the config struct
// that allows us to programmatically inspect its fields.
@ -223,6 +234,21 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
reflect.ValueOf(tower),
)
case *wtclientrpc.Config:
subCfgValue := extractReflectValue(subCfg)
if towerClient != nil {
subCfgValue.FieldByName("Active").Set(
reflect.ValueOf(towerClient != nil),
)
subCfgValue.FieldByName("Client").Set(
reflect.ValueOf(towerClient),
)
}
subCfgValue.FieldByName("Resolver").Set(
reflect.ValueOf(tcpResolver),
)
default:
return fmt.Errorf("unknown field: %v, %T", fieldName,
cfg)