github.com/ethereum-optimism/optimism@v1.7.2/op-node/node/server.go (about)

     1  package node
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"net/http"
     8  	"strconv"
     9  
    10  	ophttp "github.com/ethereum-optimism/optimism/op-service/httputil"
    11  	"github.com/ethereum/go-ethereum/log"
    12  	"github.com/ethereum/go-ethereum/node"
    13  	"github.com/ethereum/go-ethereum/rpc"
    14  
    15  	"github.com/ethereum-optimism/optimism/op-node/metrics"
    16  	"github.com/ethereum-optimism/optimism/op-node/p2p"
    17  	"github.com/ethereum-optimism/optimism/op-node/rollup"
    18  	"github.com/ethereum-optimism/optimism/op-service/sources"
    19  )
    20  
    21  type rpcServer struct {
    22  	endpoint   string
    23  	apis       []rpc.API
    24  	httpServer *ophttp.HTTPServer
    25  	appVersion string
    26  	log        log.Logger
    27  	sources.L2Client
    28  }
    29  
    30  func newRPCServer(rpcCfg *RPCConfig, rollupCfg *rollup.Config, l2Client l2EthClient, dr driverClient, safedb SafeDBReader, log log.Logger, appVersion string, m metrics.Metricer) (*rpcServer, error) {
    31  	api := NewNodeAPI(rollupCfg, l2Client, dr, safedb, log.New("rpc", "node"), m)
    32  	// TODO: extend RPC config with options for WS, IPC and HTTP RPC connections
    33  	endpoint := net.JoinHostPort(rpcCfg.ListenAddr, strconv.Itoa(rpcCfg.ListenPort))
    34  	r := &rpcServer{
    35  		endpoint: endpoint,
    36  		apis: []rpc.API{{
    37  			Namespace:     "optimism",
    38  			Service:       api,
    39  			Authenticated: false,
    40  		}},
    41  		appVersion: appVersion,
    42  		log:        log,
    43  	}
    44  	return r, nil
    45  }
    46  
    47  func (s *rpcServer) EnableAdminAPI(api *adminAPI) {
    48  	s.apis = append(s.apis, rpc.API{
    49  		Namespace:     "admin",
    50  		Version:       "",
    51  		Service:       api,
    52  		Authenticated: false,
    53  	})
    54  }
    55  
    56  func (s *rpcServer) EnableP2P(backend *p2p.APIBackend) {
    57  	s.apis = append(s.apis, rpc.API{
    58  		Namespace:     p2p.NamespaceRPC,
    59  		Version:       "",
    60  		Service:       backend,
    61  		Authenticated: false,
    62  	})
    63  }
    64  
    65  func (s *rpcServer) Start() error {
    66  	srv := rpc.NewServer()
    67  	if err := node.RegisterApis(s.apis, nil, srv); err != nil {
    68  		return err
    69  	}
    70  
    71  	// The CORS and VHosts arguments below must be set in order for
    72  	// other services to connect to the opnode. VHosts in particular
    73  	// defaults to localhost, which will prevent containers from
    74  	// calling into the opnode without an "invalid host" error.
    75  	nodeHandler := node.NewHTTPHandlerStack(srv, []string{"*"}, []string{"*"}, nil)
    76  
    77  	mux := http.NewServeMux()
    78  	mux.Handle("/", nodeHandler)
    79  	mux.HandleFunc("/healthz", healthzHandler(s.appVersion))
    80  
    81  	hs, err := ophttp.StartHTTPServer(s.endpoint, mux)
    82  	if err != nil {
    83  		return fmt.Errorf("failed to start HTTP RPC server: %w", err)
    84  	}
    85  	s.httpServer = hs
    86  	return nil
    87  }
    88  
    89  func (r *rpcServer) Stop(ctx context.Context) error {
    90  	return r.httpServer.Stop(ctx)
    91  }
    92  
    93  func (r *rpcServer) Addr() net.Addr {
    94  	return r.httpServer.Addr()
    95  }
    96  
    97  func healthzHandler(appVersion string) http.HandlerFunc {
    98  	return func(w http.ResponseWriter, r *http.Request) {
    99  		_, _ = w.Write([]byte(appVersion))
   100  	}
   101  }