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 }