From 558d63718b1e16ad24cc0f5793c4d9c375ce147c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 2 Apr 2020 15:12:28 +0200 Subject: [PATCH] rpcserver+lnrpc: register REST subservers with root server --- lnrpc/autopilotrpc/autopilot_server.go | 23 +++++++++++++++++++++++ lnrpc/chainrpc/chainnotifier_server.go | 23 +++++++++++++++++++++++ lnrpc/invoicesrpc/invoices_server.go | 23 +++++++++++++++++++++++ lnrpc/routerrpc/router_server.go | 23 +++++++++++++++++++++++ lnrpc/signrpc/signer_server.go | 23 +++++++++++++++++++++++ lnrpc/sub_server.go | 9 +++++++++ lnrpc/verrpc/server.go | 23 +++++++++++++++++++++++ lnrpc/walletrpc/walletkit_server.go | 23 +++++++++++++++++++++++ lnrpc/watchtowerrpc/handler.go | 23 +++++++++++++++++++++++ lnrpc/wtclientrpc/wtclient.go | 19 +++++++++++++++++++ rpcserver.go | 16 ++++++++++++---- 11 files changed, 224 insertions(+), 4 deletions(-) diff --git a/lnrpc/autopilotrpc/autopilot_server.go b/lnrpc/autopilotrpc/autopilot_server.go index 4a938072..fd9649ad 100644 --- a/lnrpc/autopilotrpc/autopilot_server.go +++ b/lnrpc/autopilotrpc/autopilot_server.go @@ -8,6 +8,7 @@ import ( "sync/atomic" "github.com/btcsuite/btcd/btcec" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/lnrpc" "google.golang.org/grpc" @@ -129,6 +130,28 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterAutopilotHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register Autopilot REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("Autopilot REST server successfully registered with " + + "root REST server") + return nil +} + // Status returns the current status of the autopilot agent. // // NOTE: Part of the AutopilotServer interface. diff --git a/lnrpc/chainrpc/chainnotifier_server.go b/lnrpc/chainrpc/chainnotifier_server.go index 261f7605..afa53c01 100644 --- a/lnrpc/chainrpc/chainnotifier_server.go +++ b/lnrpc/chainrpc/chainnotifier_server.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/lnrpc" "google.golang.org/grpc" @@ -189,6 +190,28 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterChainNotifierHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register ChainNotifier REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("ChainNotifier REST server successfully registered with " + + "root REST server") + return nil +} + // RegisterConfirmationsNtfn is a synchronous response-streaming RPC that // registers an intent for a client to be notified once a confirmation request // has reached its required number of confirmations on-chain. diff --git a/lnrpc/invoicesrpc/invoices_server.go b/lnrpc/invoicesrpc/invoices_server.go index 3d840a5b..75c9b7c6 100644 --- a/lnrpc/invoicesrpc/invoices_server.go +++ b/lnrpc/invoicesrpc/invoices_server.go @@ -11,6 +11,7 @@ import ( "google.golang.org/grpc" "gopkg.in/macaroon-bakery.v2/bakery" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" @@ -164,6 +165,28 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterInvoicesHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register Invoices REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("Invoices REST server successfully registered with " + + "root REST server") + return nil +} + // SubscribeSingleInvoice returns a uni-directional stream (server -> client) // for notifying the client of state changes for a specified invoice. func (s *Server) SubscribeSingleInvoice(req *SubscribeSingleInvoiceRequest, diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index c3a9215d..983090ed 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -10,6 +10,7 @@ import ( "sync/atomic" "github.com/btcsuite/btcutil" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntypes" @@ -226,6 +227,28 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterRouterHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register Router REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("Router REST server successfully registered with " + + "root REST server") + return nil +} + // SendPaymentV2 attempts to route a payment described by the passed // PaymentRequest to the final destination. If we are unable to route the // payment, or cannot find a route that satisfies the constraints in the diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index db56ac13..fca12ad7 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnrpc" @@ -174,6 +175,28 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterSignerHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register Signer REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("Signer REST server successfully registered with " + + "root REST server") + return nil +} + // 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 // correspond to the KeyLocators in the SignReq then we'll return an error. diff --git a/lnrpc/sub_server.go b/lnrpc/sub_server.go index 1e58a2a6..7970273a 100644 --- a/lnrpc/sub_server.go +++ b/lnrpc/sub_server.go @@ -1,9 +1,11 @@ package lnrpc import ( + "context" "fmt" "sync" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "google.golang.org/grpc" "gopkg.in/macaroon-bakery.v2/bakery" ) @@ -36,6 +38,13 @@ type SubServer interface { // server. Until this is called, each sub-server won't be able to have // requests routed towards it. RegisterWithRootServer(*grpc.Server) error + + // RegisterWithRestServer will be called by the root REST mux to direct + // a sub RPC server to register itself with the main REST mux server. + // Until this is called, each sub-server won't be able to have requests + // routed towards it. + RegisterWithRestServer(context.Context, *runtime.ServeMux, string, + []grpc.DialOption) error } // SubServerConfigDispatcher is an interface that all sub-servers will use to diff --git a/lnrpc/verrpc/server.go b/lnrpc/verrpc/server.go index d11c61d1..ecbd29c1 100644 --- a/lnrpc/verrpc/server.go +++ b/lnrpc/verrpc/server.go @@ -3,6 +3,7 @@ package verrpc import ( "context" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/build" "google.golang.org/grpc" "gopkg.in/macaroon-bakery.v2/bakery" @@ -57,6 +58,28 @@ func (s *Server) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (s *Server) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterVersionerHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register Versioner REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("Versioner REST server successfully registered with " + + "root REST server") + return nil +} + // GetVersion returns information about the compiled binary. func (s *Server) GetVersion(_ context.Context, _ *VersionRequest) (*Version, error) { diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 0cd8ead0..71a144f3 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/wtxmgr" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/labels" @@ -217,6 +218,28 @@ func (w *WalletKit) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (w *WalletKit) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterWalletKitHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register WalletKit REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("WalletKit REST server successfully registered with " + + "root REST server") + return nil +} + // ListUnspent returns useful information about each unspent output owned by the // wallet, as reported by the underlying `ListUnspentWitness`; the information // returned is: outpoint, amount in satoshis, address, address type, diff --git a/lnrpc/watchtowerrpc/handler.go b/lnrpc/watchtowerrpc/handler.go index fe44b92d..d4124708 100644 --- a/lnrpc/watchtowerrpc/handler.go +++ b/lnrpc/watchtowerrpc/handler.go @@ -7,6 +7,7 @@ import ( "errors" fmt "fmt" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/lnrpc" "google.golang.org/grpc" "gopkg.in/macaroon-bakery.v2/bakery" @@ -91,6 +92,28 @@ func (c *Handler) RegisterWithRootServer(grpcServer *grpc.Server) error { return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (c *Handler) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterWatchtowerHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + log.Errorf("Could not register Watchtower REST server "+ + "with root REST server: %v", err) + return err + } + + log.Debugf("Watchtower REST server successfully registered with " + + "root REST server") + return nil +} + // 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 diff --git a/lnrpc/wtclientrpc/wtclient.go b/lnrpc/wtclientrpc/wtclient.go index b6f1fa2a..acd136ef 100644 --- a/lnrpc/wtclientrpc/wtclient.go +++ b/lnrpc/wtclientrpc/wtclient.go @@ -8,6 +8,7 @@ import ( "strconv" "github.com/btcsuite/btcd/btcec" + "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" @@ -121,6 +122,24 @@ func (c *WatchtowerClient) RegisterWithRootServer(grpcServer *grpc.Server) error return nil } +// RegisterWithRestServer will be called by the root REST mux to direct a sub +// RPC server to register itself with the main REST mux server. Until this is +// called, each sub-server won't be able to have requests routed towards it. +// +// NOTE: This is part of the lnrpc.SubServer interface. +func (c *WatchtowerClient) RegisterWithRestServer(ctx context.Context, + mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error { + + // We make sure that we register it with the main REST server to ensure + // all our methods are routed properly. + err := RegisterWatchtowerClientHandlerFromEndpoint(ctx, mux, dest, opts) + if err != nil { + return err + } + + return nil +} + // isActive returns nil if the watchtower client is initialized so that we can // process RPC requests. func (c *WatchtowerClient) isActive() error { diff --git a/rpcserver.go b/rpcserver.go index 81f6f0d0..f8e713ab 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -791,23 +791,31 @@ func (r *rpcServer) Start() error { }, ) - // Finally, start the REST proxy for our gRPC server above. We'll ensure + // Now start the REST proxy for our gRPC server above. We'll ensure // we direct LND to connect to its loopback address rather than a // wildcard to prevent certificate issues when accessing the proxy // externally. - // - // TODO(roasbeef): eventually also allow the sub-servers to themselves - // have a REST proxy. restMux := proxy.NewServeMux(customMarshalerOption) restCtx, restCancel := context.WithCancel(context.Background()) r.listenerCleanUp = append(r.listenerCleanUp, restCancel) + // With our custom REST proxy mux created, register our main RPC and + // give all subservers a chance to register as well. err := lnrpc.RegisterLightningHandlerFromEndpoint( restCtx, restMux, r.restProxyDest, r.restDialOpts, ) if err != nil { return err } + for _, subServer := range r.subServers { + err := subServer.RegisterWithRestServer( + restCtx, restMux, r.restProxyDest, r.restDialOpts, + ) + if err != nil { + return fmt.Errorf("unable to register REST sub-server "+ + "%v with root: %v", subServer.Name(), err) + } + } // Before listening on any of the interfaces, we also want to give the // external subservers a chance to register their own REST proxy stub