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 }