lnrpc: wrap subservers in GrpcHandler

In order to be able to register the subservers with the root grpc server
before we have all dependencies available, we wrap them in an
GrpcHandler struct. This struct will initially hold an empty reference
to the subservers, which allows us to register with the GRPC server, and
later populate and create the subserver instance.
This commit is contained in:
Johan T. Halseth 2021-01-29 15:49:48 +01:00
parent c623d21bd2
commit 4ea494e8c5
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
20 changed files with 341 additions and 106 deletions

@ -51,6 +51,13 @@ var (
} }
) )
// 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 {
AutopilotServer
}
// Server is a sub-server of the main RPC server: the autopilot RPC. This sub // Server is a sub-server of the main RPC server: the autopilot RPC. This sub
// RPC server allows external callers to access the status of the autopilot // RPC server allows external callers to access the status of the autopilot
// currently active within lnd, as well as configuring it at runtime. // currently active within lnd, as well as configuring it at runtime.
@ -118,11 +125,11 @@ func (s *Server) Name() string {
// is called, each sub-server won't be able to have // is called, each sub-server won't be able to have
// requests routed towards it. // requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterAutopilotServer(grpcServer, s) RegisterAutopilotServer(grpcServer, r)
log.Debugf("Autopilot RPC server successfully register with root " + log.Debugf("Autopilot RPC server successfully register with root " +
"gRPC server") "gRPC server")
@ -134,8 +141,8 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -152,6 +159,25 @@ func (s *Server) RegisterWithRestServer(ctx context.Context,
return nil 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.AutopilotServer = subServer
return subServer, macPermissions, nil
}
// Status returns the current status of the autopilot agent. // Status returns the current status of the autopilot agent.
// //
// NOTE: Part of the AutopilotServer interface. // NOTE: Part of the AutopilotServer interface.

@ -13,7 +13,7 @@ import (
// that is meant for us in the config dispatcher, then we'll exit with an // that is meant for us in the config dispatcher, then we'll exit with an
// error. // error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *Server, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -48,9 +48,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.MacaroonPerms, error) { return &ServerShell{}
return createNewSubServer(c)
}, },
} }

@ -72,6 +72,13 @@ var (
"still in the process of starting") "still in the process of starting")
) )
// 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 {
ChainNotifierServer
}
// Server is a sub-server of the main RPC server: the chain notifier RPC. This // Server is a sub-server of the main RPC server: the chain notifier RPC. This
// RPC sub-server allows external callers to access the full chain notifier // RPC sub-server allows external callers to access the full chain notifier
// capabilities of lnd. This allows callers to create custom protocols, external // capabilities of lnd. This allows callers to create custom protocols, external
@ -172,11 +179,11 @@ func (s *Server) Name() string {
// sub-server to register itself with the main gRPC root server. Until this is // sub-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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterChainNotifierServer(grpcServer, s) RegisterChainNotifierServer(grpcServer, r)
log.Debug("ChainNotifier RPC server successfully register with root " + log.Debug("ChainNotifier RPC server successfully register with root " +
"gRPC server") "gRPC server")
@ -188,8 +195,8 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -206,6 +213,25 @@ func (s *Server) RegisterWithRestServer(ctx context.Context,
return nil 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.ChainNotifierServer = subServer
return subServer, macPermissions, nil
}
// RegisterConfirmationsNtfn is a synchronous response-streaming RPC that // RegisterConfirmationsNtfn is a synchronous response-streaming RPC that
// registers an intent for a client to be notified once a confirmation request // registers an intent for a client to be notified once a confirmation request
// has reached its required number of confirmations on-chain. // has reached its required number of confirmations on-chain.

@ -13,7 +13,7 @@ import (
// the config that is meant for us in the config dispatcher, then we'll exit // the config that is meant for us in the config dispatcher, then we'll exit
// with an error. // with an error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *Server, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -55,10 +55,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) ( NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { return &ServerShell{}
return createNewSubServer(c)
}, },
} }

@ -13,7 +13,7 @@ import (
// that is meant for us in the config dispatcher, then we'll exit with an // that is meant for us in the config dispatcher, then we'll exit with an
// error. // error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *Server, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -40,9 +40,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.MacaroonPerms, error) { return &ServerShell{}
return createNewSubServer(c)
}, },
} }

@ -66,6 +66,13 @@ var (
DefaultInvoicesMacFilename = "invoices.macaroon" DefaultInvoicesMacFilename = "invoices.macaroon"
) )
// 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 {
InvoicesServer
}
// Server is a sub-server of the main RPC server: the invoices RPC. This sub // Server is a sub-server of the main RPC server: the invoices RPC. This sub
// RPC server allows external callers to access the status of the invoices // RPC server allows external callers to access the status of the invoices
// currently active within lnd, as well as configuring it at runtime. // currently active within lnd, as well as configuring it at runtime.
@ -157,11 +164,11 @@ func (s *Server) Name() string {
// RPC server to register itself with the main gRPC root server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterInvoicesServer(grpcServer, s) RegisterInvoicesServer(grpcServer, r)
log.Debugf("Invoices RPC server successfully registered with root " + log.Debugf("Invoices RPC server successfully registered with root " +
"gRPC server") "gRPC server")
@ -173,8 +180,8 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -191,6 +198,25 @@ func (s *Server) RegisterWithRestServer(ctx context.Context,
return nil 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.InvoicesServer = subServer
return subServer, macPermissions, nil
}
// SubscribeSingleInvoice returns a uni-directional stream (server -> client) // SubscribeSingleInvoice returns a uni-directional stream (server -> client)
// for notifying the client of state changes for a specified invoice. // for notifying the client of state changes for a specified invoice.
func (s *Server) SubscribeSingleInvoice(req *SubscribeSingleInvoiceRequest, func (s *Server) SubscribeSingleInvoice(req *SubscribeSingleInvoiceRequest,

@ -11,7 +11,7 @@ import (
// config that is meant for us in the config dispatcher, then we'll exit with // config that is meant for us in the config dispatcher, then we'll exit with
// an error. // an error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *Server, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -46,8 +46,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, lnrpc.MacaroonPerms, error) { NewGrpcHandler: func() lnrpc.GrpcHandler {
return createNewSubServer(c) return &ServerShell{}
}, },
} }

@ -129,6 +129,13 @@ var (
DefaultRouterMacFilename = "router.macaroon" DefaultRouterMacFilename = "router.macaroon"
) )
// ServerShell a is 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 {
RouterServer
}
// Server is a stand alone sub RPC server which exposes functionality that // Server is a stand alone sub RPC server which exposes functionality that
// allows clients to route arbitrary payment through the Lightning Network. // allows clients to route arbitrary payment through the Lightning Network.
type Server struct { type Server struct {
@ -233,11 +240,11 @@ func (s *Server) Name() string {
// sub RPC server to register itself with the main gRPC root server. Until this // 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. // is called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterRouterServer(grpcServer, s) RegisterRouterServer(grpcServer, r)
log.Debugf("Router RPC server successfully register with root gRPC " + log.Debugf("Router RPC server successfully register with root gRPC " +
"server") "server")
@ -249,8 +256,8 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -267,6 +274,25 @@ func (s *Server) RegisterWithRestServer(ctx context.Context,
return nil 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.RouterServer = subServer
return subServer, macPermissions, nil
}
// SendPaymentV2 attempts to route a payment described by the passed // SendPaymentV2 attempts to route a payment described by the passed
// PaymentRequest to the final destination. If we are unable to route the // PaymentRequest to the final destination. If we are unable to route the
// payment, or cannot find a route that satisfies the constraints in the // payment, or cannot find a route that satisfies the constraints in the

@ -13,7 +13,7 @@ import (
// config that is meant for us in the config dispatcher, then we'll exit with // config that is meant for us in the config dispatcher, then we'll exit with
// an error. // an error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *Server, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -55,10 +55,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) ( NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { return &ServerShell{}
return createNewSubServer(c)
}, },
} }

@ -76,6 +76,13 @@ var (
DefaultSignerMacFilename = "signer.macaroon" DefaultSignerMacFilename = "signer.macaroon"
) )
// 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 {
SignerServer
}
// Server is a sub-server of the main RPC server: the signer RPC. This sub RPC // Server is a sub-server of the main RPC server: the signer RPC. This sub RPC
// server allows external callers to access the full signing capabilities of // server allows external callers to access the full signing capabilities of
// lnd. This allows callers to create custom protocols, external to lnd, even // lnd. This allows callers to create custom protocols, external to lnd, even
@ -167,11 +174,11 @@ func (s *Server) Name() string {
// is called, each sub-server won't be able to have // is called, each sub-server won't be able to have
// requests routed towards it. // requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterSignerServer(grpcServer, s) RegisterSignerServer(grpcServer, r)
log.Debugf("Signer RPC server successfully register with root gRPC " + log.Debugf("Signer RPC server successfully register with root gRPC " +
"server") "server")
@ -183,8 +190,8 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -201,6 +208,25 @@ func (s *Server) RegisterWithRestServer(ctx context.Context,
return nil 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.SignerServer = subServer
return subServer, macPermissions, nil
}
// SignOutputRaw generates a signature for the passed transaction according to // SignOutputRaw generates a signature for the passed transaction according to
// the data within the passed SignReq. If we're unable to find the keys that // the data within the passed SignReq. If we're unable to find the keys that
// correspond to the KeyLocators in the SignReq then we'll return an error. // correspond to the KeyLocators in the SignReq then we'll return an error.

@ -32,7 +32,14 @@ type SubServer interface {
// Name returns a unique string representation of the sub-server. This // Name returns a unique string representation of the sub-server. This
// can be used to identify the sub-server and also de-duplicate them. // can be used to identify the sub-server and also de-duplicate them.
Name() string Name() string
}
// GrpcHandler is the interface that should be registered with the root gRPC
// server, and is the interface that implements the subserver's defined RPC.
// Before the actual sub server has been created, this will be an empty shell
// allowing us to start the gRPC server before we have all the dependencies
// needed to create the subserver itself.
type GrpcHandler interface {
// RegisterWithRootServer will be called by the root gRPC server to // RegisterWithRootServer will be called by the root gRPC server to
// direct a sub RPC server to register itself with the main gRPC root // 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 // server. Until this is called, each sub-server won't be able to have
@ -45,6 +52,14 @@ type SubServer interface {
// routed towards it. // routed towards it.
RegisterWithRestServer(context.Context, *runtime.ServeMux, string, RegisterWithRestServer(context.Context, *runtime.ServeMux, string,
[]grpc.DialOption) error []grpc.DialOption) error
// 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.
CreateSubServer(subCfgs SubServerConfigDispatcher) (SubServer,
MacaroonPerms, error)
} }
// SubServerConfigDispatcher is an interface that all sub-servers will use to // SubServerConfigDispatcher is an interface that all sub-servers will use to
@ -60,22 +75,18 @@ type SubServerConfigDispatcher interface {
} }
// SubServerDriver is a template struct that allows the root server to create a // SubServerDriver is a template struct that allows the root server to create a
// sub-server with minimal knowledge. The root server only need a fully // sub-server gRPC handler with minimal knowledge.
// populated SubServerConfigDispatcher and with the aide of the
// RegisterSubServers method, it's able to create and initialize all
// sub-servers.
type SubServerDriver struct { type SubServerDriver struct {
// SubServerName is the full name of a sub-sever. // SubServerName is the full name of a sub-sever.
// //
// NOTE: This MUST be unique. // NOTE: This MUST be unique.
SubServerName string SubServerName string
// New creates, and fully initializes a new sub-server instance with // NewGrpcHandler creates a a new sub-server gRPC interface that can be
// the aide of the SubServerConfigDispatcher. This closure should // registered with the root gRPC server. It is not expected that the
// return the SubServer, ready for action, along with the set of // SubServer is ready for operation before its CreateSubServer and
// macaroon permissions that the sub-server wishes to pass on to the // Start methods have been called.
// root server for all methods routed towards it. NewGrpcHandler func() GrpcHandler
New func(subCfgs SubServerConfigDispatcher) (SubServer, MacaroonPerms, error)
} }
var ( var (

@ -9,10 +9,8 @@ import (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.MacaroonPerms, error) { return &ServerShell{}
return &Server{}, macPermissions, nil
}, },
} }

@ -5,6 +5,7 @@ import (
"github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/lnrpc"
"google.golang.org/grpc" "google.golang.org/grpc"
"gopkg.in/macaroon-bakery.v2/bakery" "gopkg.in/macaroon-bakery.v2/bakery"
) )
@ -18,6 +19,13 @@ var macPermissions = map[string][]bakery.Op{
}}, }},
} }
// 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 {
VersionerServer
}
// Server is an rpc server that supports querying for information about the // Server is an rpc server that supports querying for information about the
// running binary. // running binary.
type Server struct{} type Server struct{}
@ -48,9 +56,9 @@ func (s *Server) Name() string {
// sub RPC server to register itself with the main gRPC root server. Until this // 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. // is called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
RegisterVersionerServer(grpcServer, s) RegisterVersionerServer(grpcServer, r)
log.Debugf("Versioner RPC server successfully registered with root " + log.Debugf("Versioner RPC server successfully registered with root " +
"gRPC server") "gRPC server")
@ -62,8 +70,8 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (s *Server) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -80,6 +88,21 @@ func (s *Server) RegisterWithRestServer(ctx context.Context,
return nil 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(_ lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
subServer := &Server{}
r.VersionerServer = subServer
return subServer, macPermissions, nil
}
// GetVersion returns information about the compiled binary. // GetVersion returns information about the compiled binary.
func (s *Server) GetVersion(_ context.Context, func (s *Server) GetVersion(_ context.Context,
_ *VersionRequest) (*Version, error) { _ *VersionRequest) (*Version, error) {

@ -12,7 +12,9 @@ import (
// sub server given the main config dispatcher method. If we're unable to find // 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 // the config that is meant for us in the config dispatcher, then we'll exit
// with an error. // with an error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, lnrpc.MacaroonPerms, error) { func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
*WalletKit, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // 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 // error, as we're unable to properly initialize ourselves without this
@ -67,8 +69,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (lnrpc.S
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, lnrpc.MacaroonPerms, error) { NewGrpcHandler: func() lnrpc.GrpcHandler {
return createNewSubServer(c) return &ServerShell{}
}, },
} }

@ -148,6 +148,13 @@ var (
// an empty label. // an empty label.
var ErrZeroLabel = errors.New("cannot label transaction with empty label") var ErrZeroLabel = errors.New("cannot label transaction with empty label")
// 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 {
WalletKitServer
}
// WalletKit is a sub-RPC server that exposes a tool kit which allows clients // WalletKit is a sub-RPC server that exposes a tool kit which allows clients
// to execute common wallet operations. This includes requesting new addresses, // to execute common wallet operations. This includes requesting new addresses,
// keys (for contracts!), and publishing transactions. // keys (for contracts!), and publishing transactions.
@ -233,11 +240,11 @@ func (w *WalletKit) Name() string {
// sub RPC server to register itself with the main gRPC root server. Until this // 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. // is called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (w *WalletKit) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterWalletKitServer(grpcServer, w) RegisterWalletKitServer(grpcServer, r)
log.Debugf("WalletKit RPC server successfully registered with " + log.Debugf("WalletKit RPC server successfully registered with " +
"root gRPC server") "root gRPC server")
@ -249,8 +256,8 @@ func (w *WalletKit) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (w *WalletKit) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -267,6 +274,25 @@ func (w *WalletKit) RegisterWithRestServer(ctx context.Context,
return nil 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.WalletKitServer = subServer
return subServer, macPermissions, nil
}
// ListUnspent returns useful information about each unspent output owned by the // ListUnspent returns useful information about each unspent output owned by the
// wallet, as reported by the underlying `ListUnspentWitness`; the information // wallet, as reported by the underlying `ListUnspentWitness`; the information
// returned is: outpoint, amount in satoshis, address, address type, // returned is: outpoint, amount in satoshis, address, address type,

@ -13,7 +13,7 @@ import (
// that is meant for us in the config dispatcher, then we'll exit with an // that is meant for us in the config dispatcher, then we'll exit with an
// error. // error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *Handler, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -40,9 +40,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.MacaroonPerms, error) { return &ServerShell{}
return createNewSubServer(c)
}, },
} }

@ -5,7 +5,7 @@ package watchtowerrpc
import ( import (
"context" "context"
"errors" "errors"
fmt "fmt" "fmt"
"github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
@ -35,6 +35,13 @@ var (
ErrTowerNotActive = errors.New("watchtower not active") ErrTowerNotActive = errors.New("watchtower not active")
) )
// 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 {
WatchtowerServer
}
// Handler is the RPC server we'll use to interact with the backing active // Handler is the RPC server we'll use to interact with the backing active
// watchtower. // watchtower.
type Handler struct { type Handler struct {
@ -80,11 +87,11 @@ func (c *Handler) Name() string {
// RPC server to register itself with the main gRPC root server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (c *Handler) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterWatchtowerServer(grpcServer, c) RegisterWatchtowerServer(grpcServer, r)
log.Debugf("Watchtower RPC server successfully register with root " + log.Debugf("Watchtower RPC server successfully register with root " +
"gRPC server") "gRPC server")
@ -96,8 +103,8 @@ func (c *Handler) RegisterWithRootServer(grpcServer *grpc.Server) error {
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (c *Handler) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -114,6 +121,25 @@ func (c *Handler) RegisterWithRestServer(ctx context.Context,
return nil 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.WatchtowerServer = subServer
return subServer, macPermissions, nil
}
// AddTower adds a new watchtower reachable at the given address and considers // 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 // it for new sessions. If the watchtower already exists, then any new addresses
// included will be considered when dialing it for session negotiations and // included will be considered when dialing it for session negotiations and

@ -12,7 +12,7 @@ import (
// that is meant for us in the config dispatcher, then we'll exit with an // that is meant for us in the config dispatcher, then we'll exit with an
// error. // error.
func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) ( func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
lnrpc.SubServer, lnrpc.MacaroonPerms, error) { *WatchtowerClient, lnrpc.MacaroonPerms, error) {
// We'll attempt to look up the config that we expect, according to our // 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 // subServerName name. If we can't find this, then we'll exit with an
@ -46,9 +46,8 @@ func createNewSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
func init() { func init() {
subServer := &lnrpc.SubServerDriver{ subServer := &lnrpc.SubServerDriver{
SubServerName: subServerName, SubServerName: subServerName,
New: func(c lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer, NewGrpcHandler: func() lnrpc.GrpcHandler {
lnrpc.MacaroonPerms, error) { return &ServerShell{}
return createNewSubServer(c)
}, },
} }

@ -64,6 +64,13 @@ var (
ErrWtclientNotActive = errors.New("watchtower client not active") ErrWtclientNotActive = errors.New("watchtower client not active")
) )
// 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 {
WatchtowerClientServer
}
// WatchtowerClient is the RPC server we'll use to interact with the backing // WatchtowerClient is the RPC server we'll use to interact with the backing
// active watchtower client. // active watchtower client.
// //
@ -112,14 +119,11 @@ func (c *WatchtowerClient) Name() string {
// RPC server to register itself with the main gRPC root server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (c *WatchtowerClient) RegisterWithRootServer(grpcServer *grpc.Server) error { func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
// We make sure that we register it with the main gRPC server to ensure // We make sure that we register it with the main gRPC server to ensure
// all our methods are routed properly. // all our methods are routed properly.
RegisterWatchtowerClientServer(grpcServer, c) RegisterWatchtowerClientServer(grpcServer, r)
c.cfg.Log.Debugf("WatchtowerClient RPC server successfully registered " +
"with root gRPC server")
return nil return nil
} }
@ -128,8 +132,8 @@ func (c *WatchtowerClient) RegisterWithRootServer(grpcServer *grpc.Server) error
// RPC server to register itself with the main REST mux server. Until this is // 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. // called, each sub-server won't be able to have requests routed towards it.
// //
// NOTE: This is part of the lnrpc.SubServer interface. // NOTE: This is part of the lnrpc.GrpcHandler interface.
func (c *WatchtowerClient) RegisterWithRestServer(ctx context.Context, func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
// We make sure that we register it with the main REST server to ensure // We make sure that we register it with the main REST server to ensure
@ -142,6 +146,25 @@ func (c *WatchtowerClient) RegisterWithRestServer(ctx context.Context,
return nil 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.WatchtowerClientServer = subServer
return subServer, macPermissions, nil
}
// isActive returns nil if the watchtower client is initialized so that we can // isActive returns nil if the watchtower client is initialized so that we can
// process RPC requests. // process RPC requests.
func (c *WatchtowerClient) isActive() error { func (c *WatchtowerClient) isActive() error {

@ -492,7 +492,8 @@ type rpcServer struct {
// own independent service. This allows us to expose a set of // own independent service. This allows us to expose a set of
// micro-service like abstractions to the outside world for users to // micro-service like abstractions to the outside world for users to
// consume. // consume.
subServers []lnrpc.SubServer subServers []lnrpc.SubServer
subGrpcHandlers []lnrpc.GrpcHandler
// grpcServer is the main gRPC server that this RPC server, and all the // grpcServer is the main gRPC server that this RPC server, and all the
// sub-servers will use to register themselves and accept client // sub-servers will use to register themselves and accept client
@ -616,8 +617,9 @@ func newRPCServer(cfg *Config, s *server, macService *macaroons.Service,
} }
var ( var (
subServers []lnrpc.SubServer subServers []lnrpc.SubServer
subServerPerms []lnrpc.MacaroonPerms subGrpcHandlers []lnrpc.GrpcHandler
subServerPerms []lnrpc.MacaroonPerms
) )
// Before we create any of the sub-servers, we need to ensure that all // Before we create any of the sub-servers, we need to ensure that all
@ -639,8 +641,9 @@ func newRPCServer(cfg *Config, s *server, macService *macaroons.Service,
// Now that the sub-servers have all their dependencies in place, we // Now that the sub-servers have all their dependencies in place, we
// can create each sub-server! // can create each sub-server!
registeredSubServers := lnrpc.RegisteredSubServers() registeredSubServers := lnrpc.RegisteredSubServers()
for _, subServer := range registeredSubServers { for _, driver := range registeredSubServers {
subServerInstance, macPerms, err := subServer.New(subServerCgs) handler := driver.NewGrpcHandler()
subServer, macPerms, err := handler.CreateSubServer(subServerCgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -648,7 +651,8 @@ func newRPCServer(cfg *Config, s *server, macService *macaroons.Service,
// We'll collect the sub-server, and also the set of // We'll collect the sub-server, and also the set of
// permissions it needs for macaroons so we can apply the // permissions it needs for macaroons so we can apply the
// interceptors below. // interceptors below.
subServers = append(subServers, subServerInstance) subServers = append(subServers, subServer)
subGrpcHandlers = append(subGrpcHandlers, handler)
subServerPerms = append(subServerPerms, macPerms) subServerPerms = append(subServerPerms, macPerms)
} }
@ -767,6 +771,7 @@ func newRPCServer(cfg *Config, s *server, macService *macaroons.Service,
listenerCleanUp: []func(){cleanup}, listenerCleanUp: []func(){cleanup},
restProxyDest: restProxyDest, restProxyDest: restProxyDest,
subServers: subServers, subServers: subServers,
subGrpcHandlers: subGrpcHandlers,
restListen: restListen, restListen: restListen,
grpcServer: grpcServer, grpcServer: grpcServer,
server: s, server: s,
@ -782,12 +787,11 @@ func newRPCServer(cfg *Config, s *server, macService *macaroons.Service,
// Now the main RPC server has been registered, we'll iterate through // Now the main RPC server has been registered, we'll iterate through
// all the sub-RPC servers and register them to ensure that requests // all the sub-RPC servers and register them to ensure that requests
// are properly routed towards them. // are properly routed towards them.
for _, subServer := range subServers { for _, subServer := range subGrpcHandlers {
err := subServer.RegisterWithRootServer(grpcServer) err := subServer.RegisterWithRootServer(grpcServer)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to register "+ return nil, fmt.Errorf("unable to register "+
"sub-server %v with root: %v", "sub-server with root: %v", err)
subServer.Name(), err)
} }
} }
@ -885,13 +889,13 @@ func (r *rpcServer) Start() error {
if err != nil { if err != nil {
return err return err
} }
for _, subServer := range r.subServers { for _, subServer := range r.subGrpcHandlers {
err := subServer.RegisterWithRestServer( err := subServer.RegisterWithRestServer(
restCtx, restMux, r.restProxyDest, r.restDialOpts, restCtx, restMux, r.restProxyDest, r.restDialOpts,
) )
if err != nil { if err != nil {
return fmt.Errorf("unable to register REST sub-server "+ return fmt.Errorf("unable to register REST sub-server "+
"%v with root: %v", subServer.Name(), err) "with root: %v", err)
} }
} }