github.com/decred/dcrlnd@v0.7.6/lnrpc/watchtowerrpc/handler.go (about)

     1  //go:build !no_watchtowerrpc
     2  // +build !no_watchtowerrpc
     3  
     4  package watchtowerrpc
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"fmt"
    10  
    11  	"github.com/decred/dcrlnd/lnrpc"
    12  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    13  	"google.golang.org/grpc"
    14  	"gopkg.in/macaroon-bakery.v2/bakery"
    15  )
    16  
    17  const (
    18  	// subServerName is the name of the sub rpc server. We'll use this name
    19  	// to register ourselves, and we also require that the main
    20  	// SubServerConfigDispatcher instance recognizes it as the name of our
    21  	// RPC service.
    22  	subServerName = "WatchtowerRPC"
    23  )
    24  
    25  var (
    26  	// macPermissions maps RPC calls to the permissions they require.
    27  	macPermissions = map[string][]bakery.Op{
    28  		"/watchtowerrpc.Watchtower/GetInfo": {{
    29  			Entity: "info",
    30  			Action: "read",
    31  		}},
    32  	}
    33  
    34  	// ErrTowerNotActive signals that RPC calls cannot be processed because
    35  	// the watchtower is not active.
    36  	ErrTowerNotActive = errors.New("watchtower not active")
    37  )
    38  
    39  // ServerShell is a shell struct holding a reference to the actual sub-server.
    40  // It is used to register the gRPC sub-server with the root server before we
    41  // have the necessary dependencies to populate the actual sub-server.
    42  type ServerShell struct {
    43  	WatchtowerServer
    44  }
    45  
    46  // Handler is the RPC server we'll use to interact with the backing active
    47  // watchtower.
    48  type Handler struct {
    49  	cfg Config
    50  }
    51  
    52  // A compile time check to ensure that Handler fully implements the Handler gRPC
    53  // service.
    54  var _ WatchtowerServer = (*Handler)(nil)
    55  
    56  // New returns a new instance of the Watchtower sub-server. We also return the
    57  // set of permissions for the macaroons that we may create within this method.
    58  // If the macaroons we need aren't found in the filepath, then we'll create them
    59  // on start up. If we're unable to locate, or create the macaroons we need, then
    60  // we'll return with an error.
    61  func New(cfg *Config) (*Handler, lnrpc.MacaroonPerms, error) {
    62  	return &Handler{*cfg}, macPermissions, nil
    63  }
    64  
    65  // Start launches any helper goroutines required for the Handler to function.
    66  //
    67  // NOTE: This is part of the lnrpc.SubServer interface.
    68  func (c *Handler) Start() error {
    69  	return nil
    70  }
    71  
    72  // Stop signals any active goroutines for a graceful closure.
    73  //
    74  // NOTE: This is part of the lnrpc.SubServer interface.
    75  func (c *Handler) Stop() error {
    76  	return nil
    77  }
    78  
    79  // Name returns a unique string representation of the sub-server. This can be
    80  // used to identify the sub-server and also de-duplicate them.
    81  //
    82  // NOTE: This is part of the lnrpc.SubServer interface.
    83  func (c *Handler) Name() string {
    84  	return subServerName
    85  }
    86  
    87  // RegisterWithRootServer will be called by the root gRPC server to direct a sub
    88  // RPC server to register itself with the main gRPC root server. Until this is
    89  // called, each sub-server won't be able to have requests routed towards it.
    90  //
    91  // NOTE: This is part of the lnrpc.GrpcHandler interface.
    92  func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
    93  	// We make sure that we register it with the main gRPC server to ensure
    94  	// all our methods are routed properly.
    95  	RegisterWatchtowerServer(grpcServer, r)
    96  
    97  	log.Debugf("Watchtower RPC server successfully register with root " +
    98  		"gRPC server")
    99  
   100  	return nil
   101  }
   102  
   103  // RegisterWithRestServer will be called by the root REST mux to direct a sub
   104  // RPC server to register itself with the main REST mux server. Until this is
   105  // called, each sub-server won't be able to have requests routed towards it.
   106  //
   107  // NOTE: This is part of the lnrpc.GrpcHandler interface.
   108  func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
   109  	mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
   110  
   111  	// We make sure that we register it with the main REST server to ensure
   112  	// all our methods are routed properly.
   113  	err := RegisterWatchtowerHandlerFromEndpoint(ctx, mux, dest, opts)
   114  	if err != nil {
   115  		log.Errorf("Could not register Watchtower REST server "+
   116  			"with root REST server: %v", err)
   117  		return err
   118  	}
   119  
   120  	log.Debugf("Watchtower REST server successfully registered with " +
   121  		"root REST server")
   122  	return nil
   123  }
   124  
   125  // CreateSubServer populates the subserver's dependencies using the passed
   126  // SubServerConfigDispatcher. This method should fully initialize the
   127  // sub-server instance, making it ready for action. It returns the macaroon
   128  // permissions that the sub-server wishes to pass on to the root server for all
   129  // methods routed towards it.
   130  //
   131  // NOTE: This is part of the lnrpc.GrpcHandler interface.
   132  func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
   133  	lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
   134  
   135  	subServer, macPermissions, err := createNewSubServer(configRegistry)
   136  	if err != nil {
   137  		return nil, nil, err
   138  	}
   139  
   140  	r.WatchtowerServer = subServer
   141  	return subServer, macPermissions, nil
   142  }
   143  
   144  // AddTower adds a new watchtower reachable at the given address and considers
   145  // it for new sessions. If the watchtower already exists, then any new addresses
   146  // included will be considered when dialing it for session negotiations and
   147  // backups.
   148  func (c *Handler) GetInfo(ctx context.Context,
   149  	req *GetInfoRequest) (*GetInfoResponse, error) {
   150  
   151  	if err := c.isActive(); err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	pubkey := c.cfg.Tower.PubKey().SerializeCompressed()
   156  
   157  	var listeners []string
   158  	for _, addr := range c.cfg.Tower.ListeningAddrs() {
   159  		listeners = append(listeners, addr.String())
   160  	}
   161  
   162  	var uris []string
   163  	for _, addr := range c.cfg.Tower.ExternalIPs() {
   164  		uris = append(uris, fmt.Sprintf("%x@%v", pubkey, addr))
   165  	}
   166  
   167  	return &GetInfoResponse{
   168  		Pubkey:    pubkey,
   169  		Listeners: listeners,
   170  		Uris:      uris,
   171  	}, nil
   172  }
   173  
   174  // isActive returns nil if the tower backend is initialized, and the Handler can
   175  // proccess RPC requests.
   176  func (c *Handler) isActive() error {
   177  	if c.cfg.Active {
   178  		return nil
   179  	}
   180  	return ErrTowerNotActive
   181  }