From cddfe74b678747885e6165af8cc6169db49ae3e2 Mon Sep 17 00:00:00 2001 From: tbjump <103955289+tbjump@users.noreply.github.com> Date: Fri, 18 Nov 2022 07:36:22 -0800 Subject: [PATCH] node: forward public REST requests to public gRPC (#1695) * forward public REST requests to public gRPC * handle publicPRC address differently * add config flag publicGRPCSocketPath * start publicrpcsocket and forward publicweb to publicrpcsocket * clarify error message * add --publicGRPCSocket to testnet Co-authored-by: tbjump <> --- devnet/node.yaml | 4 ++- node/cmd/guardiand/node.go | 59 ++++++++++++++++++++++----------- node/cmd/guardiand/publicrpc.go | 45 +++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/devnet/node.yaml b/devnet/node.yaml index 7bae8b4c2..0db4e5379 100644 --- a/devnet/node.yaml +++ b/devnet/node.yaml @@ -89,7 +89,7 @@ spec: - --arbitrumRPC - ws://eth-devnet:8545 - --optimismRPC - - ws://eth-devnet:8545 + - ws://eth-devnet:8545 - --neonRPC - ws://eth-devnet:8545 # - --wormchainWS @@ -139,6 +139,8 @@ spec: - "[::]:7071" - --adminSocket - /tmp/admin.sock + - --publicGRPCSocket + - /tmp/publicrpc.sock - --dataDir - /tmp/data # - --chainGovernorEnabled=true diff --git a/node/cmd/guardiand/node.go b/node/cmd/guardiand/node.go index 2ddd7ad9f..530fc7f5b 100644 --- a/node/cmd/guardiand/node.go +++ b/node/cmd/guardiand/node.go @@ -61,7 +61,8 @@ var ( nodeKeyPath *string - adminSocketPath *string + adminSocketPath *string + publicGRPCSocketPath *string dataDir *string @@ -200,6 +201,7 @@ func init() { nodeKeyPath = NodeCmd.Flags().String("nodeKey", "", "Path to node key (will be generated if it doesn't exist)") adminSocketPath = NodeCmd.Flags().String("adminSocket", "", "Admin gRPC service UNIX domain socket path") + publicGRPCSocketPath = NodeCmd.Flags().String("publicGRPCSocket", "", "Public gRPC service UNIX domain socket path") dataDir = NodeCmd.Flags().String("dataDir", "", "Data directory") @@ -478,6 +480,12 @@ func runNode(cmd *cobra.Command, args []string) { if *adminSocketPath == "" { logger.Fatal("Please specify --adminSocket") } + if *adminSocketPath == *publicGRPCSocketPath { + logger.Fatal("--adminSocket must not equal --publicGRPCSocket") + } + if (*publicRPC != "" || *publicWeb != "") && *publicGRPCSocketPath == "" { + logger.Fatal("If either --publicRPC or --publicWeb is specified, --publicGRPCSocket must also be specified") + } if *dataDir == "" { logger.Fatal("Please specify --dataDir") } @@ -902,24 +910,12 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("chain governor is disabled") } - publicrpcService, publicrpcServer, err := publicrpcServiceRunnable(logger, *publicRPC, db, gst, gov) - - if err != nil { - log.Fatal("failed to create publicrpc service socket", zap.Error(err)) - } - // local admin service socket adminService, err := adminServiceRunnable(logger, *adminSocketPath, injectC, signedInC, obsvReqSendC, db, gst, gov) if err != nil { logger.Fatal("failed to create admin service socket", zap.Error(err)) } - publicwebService, err := publicwebServiceRunnable(logger, *publicWeb, *adminSocketPath, publicrpcServer, - *tlsHostname, *tlsProdEnv, path.Join(*dataDir, "autocert")) - if err != nil { - log.Fatal("failed to create publicrpc service socket", zap.Error(err)) - } - // Run supervisor. supervisor.New(rootCtx, logger, func(ctx context.Context) error { if err := supervisor.Run(ctx, "p2p", p2p.Run( @@ -1249,14 +1245,39 @@ func runNode(cmd *cobra.Command, args []string) { if err := supervisor.Run(ctx, "admin", adminService); err != nil { return err } - if *publicRPC != "" { - if err := supervisor.Run(ctx, "publicrpc", publicrpcService); err != nil { + + if shouldStart(publicGRPCSocketPath) { + + // local public grpc service socket + publicrpcUnixService, publicrpcServer, err := publicrpcUnixServiceRunnable(logger, *publicGRPCSocketPath, db, gst, gov) + if err != nil { + logger.Fatal("failed to create publicrpc service socket", zap.Error(err)) + } + + if err := supervisor.Run(ctx, "publicrpcsocket", publicrpcUnixService); err != nil { return err } - } - if *publicWeb != "" { - if err := supervisor.Run(ctx, "publicweb", publicwebService); err != nil { - return err + + if shouldStart(publicRPC) { + publicrpcService, err := publicrpcTcpServiceRunnable(logger, *publicRPC, db, gst, gov) + if err != nil { + log.Fatal("failed to create publicrpc tcp service", zap.Error(err)) + } + if err := supervisor.Run(ctx, "publicrpc", publicrpcService); err != nil { + return err + } + } + + if shouldStart(publicWeb) { + publicwebService, err := publicwebServiceRunnable(logger, *publicWeb, *publicGRPCSocketPath, publicrpcServer, + *tlsHostname, *tlsProdEnv, path.Join(*dataDir, "autocert")) + if err != nil { + log.Fatal("failed to create publicrpc web service", zap.Error(err)) + } + + if err := supervisor.Run(ctx, "publicweb", publicwebService); err != nil { + return err + } } } diff --git a/node/cmd/guardiand/publicrpc.go b/node/cmd/guardiand/publicrpc.go index 39ed59c19..b308c5c30 100644 --- a/node/cmd/guardiand/publicrpc.go +++ b/node/cmd/guardiand/publicrpc.go @@ -3,6 +3,7 @@ package guardiand import ( "fmt" "net" + "os" "github.com/certusone/wormhole/node/pkg/common" "github.com/certusone/wormhole/node/pkg/db" @@ -14,10 +15,11 @@ import ( "google.golang.org/grpc" ) -func publicrpcServiceRunnable(logger *zap.Logger, listenAddr string, db *db.Database, gst *common.GuardianSetState, gov *governor.ChainGovernor) (supervisor.Runnable, *grpc.Server, error) { +func publicrpcTcpServiceRunnable(logger *zap.Logger, listenAddr string, db *db.Database, gst *common.GuardianSetState, gov *governor.ChainGovernor) (supervisor.Runnable, error) { l, err := net.Listen("tcp", listenAddr) + if err != nil { - return nil, nil, fmt.Errorf("failed to listen: %w", err) + return nil, fmt.Errorf("failed to listen: %w", err) } logger.Info("publicrpc server listening", zap.String("addr", l.Addr().String())) @@ -26,5 +28,44 @@ func publicrpcServiceRunnable(logger *zap.Logger, listenAddr string, db *db.Data grpcServer := common.NewInstrumentedGRPCServer(logger) publicrpcv1.RegisterPublicRPCServiceServer(grpcServer, rpcServer) + return supervisor.GRPCServer(grpcServer, l, false), nil +} + +func publicrpcUnixServiceRunnable(logger *zap.Logger, socketPath string, db *db.Database, gst *common.GuardianSetState, gov *governor.ChainGovernor) (supervisor.Runnable, *grpc.Server, error) { + // Delete existing UNIX socket, if present. + fi, err := os.Stat(socketPath) + if err == nil { + fmode := fi.Mode() + if fmode&os.ModeType == os.ModeSocket { + err = os.Remove(socketPath) + if err != nil { + return nil, nil, fmt.Errorf("failed to remove existing socket at %s: %w", socketPath, err) + } + } else { + return nil, nil, fmt.Errorf("%s is not a UNIX socket", socketPath) + } + } + + // Create a new UNIX socket and listen to it. + + // The socket is created with the default umask. We set a restrictive umask in setRestrictiveUmask + // to ensure that any files we create are only readable by the user - this is much harder to mess up. + // The umask avoids a race condition between file creation and chmod. + + laddr, err := net.ResolveUnixAddr("unix", socketPath) + if err != nil { + return nil, nil, fmt.Errorf("invalid listen address: %v", err) + } + l, err := net.ListenUnix("unix", laddr) + if err != nil { + return nil, nil, fmt.Errorf("failed to listen on %s: %w", socketPath, err) + } + + logger.Info("publicrpc (unix socket) server listening on", zap.String("path", socketPath)) + + publicrpcService := publicrpc.NewPublicrpcServer(logger, db, gst, gov) + + grpcServer := common.NewInstrumentedGRPCServer(logger) + publicrpcv1.RegisterPublicRPCServiceServer(grpcServer, publicrpcService) return supervisor.GRPCServer(grpcServer, l, false), grpcServer, nil }