github.com/klaytn/klaytn@v1.10.2/node/node.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of go-ethereum.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from node/node.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package node
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"net"
    27  	"os"
    28  	"path/filepath"
    29  	"reflect"
    30  	"runtime"
    31  	"strconv"
    32  	"strings"
    33  	"sync"
    34  	"time"
    35  
    36  	"github.com/bt51/ntpclient"
    37  	"github.com/klaytn/klaytn/accounts"
    38  	"github.com/klaytn/klaytn/api/debug"
    39  	"github.com/klaytn/klaytn/event"
    40  	"github.com/klaytn/klaytn/log"
    41  	metricutils "github.com/klaytn/klaytn/metrics/utils"
    42  	"github.com/klaytn/klaytn/networks/grpc"
    43  	"github.com/klaytn/klaytn/networks/p2p"
    44  	"github.com/klaytn/klaytn/networks/rpc"
    45  	"github.com/klaytn/klaytn/storage/database"
    46  	"github.com/prometheus/client_golang/prometheus"
    47  	"github.com/prometheus/prometheus/util/flock"
    48  )
    49  
    50  var logger = log.NewModuleLogger(log.Node)
    51  
    52  // Node is a container on which services can be registered.
    53  type Node struct {
    54  	eventmux *event.TypeMux
    55  	config   *Config
    56  	accman   *accounts.Manager
    57  
    58  	ephemeralKeystore string
    59  	instanceDirLock   flock.Releaser
    60  
    61  	serverConfig p2p.Config
    62  	server       p2p.Server
    63  
    64  	coreServiceFuncs []ServiceConstructor
    65  	serviceFuncs     []ServiceConstructor
    66  
    67  	subservices map[reflect.Type]Service // services to be terminated previously
    68  	services    map[reflect.Type]Service // Currently running services
    69  
    70  	rpcAPIs       []rpc.API
    71  	inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
    72  
    73  	ipcEndpoint string       // IPC endpoint to listen at (empty = IPC disabled)
    74  	ipcListener net.Listener // IPC RPC listener socket to serve API requests
    75  	ipcHandler  *rpc.Server  // IPC RPC request handler to process the API requests
    76  
    77  	httpEndpoint  string       // HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
    78  	httpWhitelist []string     // HTTP RPC modules to allow through this endpoint
    79  	httpListener  net.Listener // HTTP RPC listener socket to server API requests
    80  	httpHandler   *rpc.Server  // HTTP RPC request handler to process the API requests
    81  
    82  	wsEndpoint string       // Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
    83  	wsListener net.Listener // Websocket RPC listener socket to server API requests
    84  	wsHandler  *rpc.Server  // Websocket RPC request handler to process the API requests
    85  
    86  	grpcEndpoint string         // gRPC endpoint (interface + port) to listen at (empty = gRPC disabled)
    87  	grpcListener *grpc.Listener // gRPC listener socket to server API requests
    88  	grpcHandler  *rpc.Server    // gRPC request handler to process the API requests
    89  
    90  	stop chan struct{} // Channel to wait for termination notifications
    91  	lock sync.RWMutex
    92  
    93  	logger log.Logger
    94  }
    95  
    96  // New creates a new P2P node, ready for protocol registration.
    97  func New(conf *Config) (*Node, error) {
    98  	// Copy config and resolve the datadir so future changes to the current
    99  	// working directory don't affect the node.
   100  	confCopy := *conf
   101  	conf = &confCopy
   102  	if conf.DataDir != "" {
   103  		absdatadir, err := filepath.Abs(conf.DataDir)
   104  		if err != nil {
   105  			return nil, err
   106  		}
   107  		conf.DataDir = absdatadir
   108  	}
   109  	// Ensure that the instance name doesn't cause weird conflicts with
   110  	// other files in the data directory.
   111  	if strings.ContainsAny(conf.Name, `/\`) {
   112  		return nil, errors.New(`Config.Name must not contain '/' or '\'`)
   113  	}
   114  	if conf.Name == datadirDefaultKeyStore {
   115  		return nil, errors.New(`Config.Name cannot be "` + datadirDefaultKeyStore + `"`)
   116  	}
   117  	if strings.HasSuffix(conf.Name, ".ipc") {
   118  		return nil, errors.New(`Config.Name cannot end in ".ipc"`)
   119  	}
   120  
   121  	// Ensure that the AccountManager method works before the node has started.
   122  	// We rely on this in cmd/{kcn,ken,kpn}.
   123  	am, ephemeralKeystore, err := makeAccountManager(conf)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	if conf.Logger == nil {
   128  		conf.Logger = logger
   129  	}
   130  
   131  	// Note: any interaction with Config that would create/touch files
   132  	// in the data directory or instance directory is delayed until Start.
   133  	return &Node{
   134  		accman:            am,
   135  		ephemeralKeystore: ephemeralKeystore,
   136  		config:            conf,
   137  		coreServiceFuncs:  []ServiceConstructor{},
   138  		serviceFuncs:      []ServiceConstructor{},
   139  		ipcEndpoint:       conf.IPCEndpoint(),
   140  		httpEndpoint:      conf.HTTPEndpoint(),
   141  		wsEndpoint:        conf.WSEndpoint(),
   142  		grpcEndpoint:      conf.GRPCEndpoint(),
   143  		eventmux:          new(event.TypeMux),
   144  		logger:            conf.Logger,
   145  	}, nil
   146  }
   147  
   148  // Register injects a new service into the node's stack. The service created by
   149  // the passed constructor must be unique in its type with regard to sibling ones.
   150  func (n *Node) Register(constructor ServiceConstructor) error {
   151  	n.lock.Lock()
   152  	defer n.lock.Unlock()
   153  
   154  	if n.server != nil {
   155  		return ErrNodeRunning
   156  	}
   157  	n.coreServiceFuncs = append(n.coreServiceFuncs, constructor)
   158  	return nil
   159  }
   160  
   161  func (n *Node) RegisterSubService(constructor ServiceConstructor) error {
   162  	n.lock.Lock()
   163  	defer n.lock.Unlock()
   164  
   165  	if n.server != nil {
   166  		return ErrNodeRunning
   167  	}
   168  	n.serviceFuncs = append(n.serviceFuncs, constructor)
   169  	return nil
   170  }
   171  
   172  func (n *Node) Start() error {
   173  	n.lock.Lock()
   174  	defer n.lock.Unlock()
   175  
   176  	if n.server != nil {
   177  		return ErrNodeRunning
   178  	}
   179  	if err := n.openDataDir(); err != nil {
   180  		return err
   181  	}
   182  
   183  	n.serverConfig = n.config.P2P
   184  	n.serverConfig.PrivateKey = n.config.NodeKey()
   185  	n.serverConfig.Name = n.config.NodeName()
   186  	n.serverConfig.Logger = n.logger
   187  	if n.serverConfig.StaticNodes == nil {
   188  		n.serverConfig.StaticNodes = n.config.StaticNodes()
   189  	}
   190  	if n.serverConfig.TrustedNodes == nil {
   191  		n.serverConfig.TrustedNodes = n.config.TrustedNodes()
   192  	}
   193  	if n.serverConfig.NodeDatabase == "" {
   194  		n.serverConfig.NodeDatabase = n.config.NodeDB()
   195  	}
   196  
   197  	p2pServer := p2p.NewServer(n.serverConfig)
   198  	n.logger.Info("Starting peer-to-peer node", "instance", n.serverConfig.Name)
   199  
   200  	// Otherwise copy and specialize the P2P configuration
   201  	coreservices := make(map[reflect.Type]Service)
   202  	if err := n.initService(n.coreServiceFuncs, coreservices); err != nil {
   203  		return err
   204  	}
   205  
   206  	services := make(map[reflect.Type]Service)
   207  	if err := n.initService(n.serviceFuncs, services); err != nil {
   208  		return err
   209  	}
   210  
   211  	// Gather the protocols and start the freshly assembled P2P server
   212  	for _, service := range coreservices {
   213  		if len(service.Protocols()) > 0 {
   214  			p2pServer.AddProtocols(service.Protocols())
   215  		}
   216  		for _, s := range services {
   217  			// TODO-Klaytn-ServiceChain call setcomponents repeatedly for same component
   218  			s.SetComponents(service.Components())
   219  		}
   220  	}
   221  	if err := p2pServer.Start(); err != nil {
   222  		return convertFileLockError(err)
   223  	}
   224  
   225  	// Start each of the coreservices
   226  	coreStarted := []reflect.Type{}
   227  	for kind, service := range coreservices {
   228  		// Start the next service, stopping all previous upon failure
   229  		if err := service.Start(p2pServer); err != nil {
   230  			for _, kind := range coreStarted {
   231  				coreservices[kind].Stop()
   232  			}
   233  			p2pServer.Stop()
   234  
   235  			return err
   236  		}
   237  		// Mark the service started for potential cleanup
   238  		coreStarted = append(coreStarted, kind)
   239  	}
   240  
   241  	started := []reflect.Type{}
   242  	for kind, service := range services {
   243  		if err := service.Start(p2pServer); err != nil {
   244  			for _, kind := range started {
   245  				services[kind].Stop()
   246  			}
   247  			for _, kind := range coreStarted {
   248  				coreservices[kind].Stop()
   249  			}
   250  			p2pServer.Stop()
   251  
   252  			return err
   253  		}
   254  		// Mark the service started for potential cleanup
   255  		started = append(started, kind)
   256  	}
   257  
   258  	for kind, service := range services {
   259  		coreservices[kind] = service
   260  	}
   261  
   262  	// Lastly start the configured RPC interfaces
   263  	if err := n.startRPC(coreservices); err != nil {
   264  		for _, service := range coreservices {
   265  			service.Stop()
   266  		}
   267  		p2pServer.Stop()
   268  		return err
   269  	}
   270  
   271  	// Finish initializing the startup
   272  	n.subservices = services
   273  	n.services = coreservices
   274  	n.server = p2pServer
   275  	n.stop = make(chan struct{})
   276  
   277  	// Register a labeled metric containing version and build information
   278  	// e.g.) klaytn_build_info{version="v1.8.4+b3ab199674" cpu_arch="darwin-arm64" go_version="go1.18.2"} 1
   279  	if metricutils.Enabled {
   280  		buildInfo := prometheus.NewGauge(prometheus.GaugeOpts{
   281  			Namespace:   metricutils.MetricNamespace,
   282  			Subsystem:   "",
   283  			Name:        "build_info",
   284  			Help:        "A metric with a constant '1' value labeled by version",
   285  			ConstLabels: prometheus.Labels{"version": n.config.Version, "cpu_arch": runtime.GOARCH, "go_version": runtime.Version()},
   286  		})
   287  		buildInfo.Set(1.0) // dummy value
   288  		prometheus.DefaultRegisterer.MustRegister(buildInfo)
   289  	}
   290  	return nil
   291  }
   292  
   293  func (n *Node) initService(serviceFunc []ServiceConstructor, services map[reflect.Type]Service) error {
   294  	for _, constructor := range serviceFunc {
   295  		// Create a new context for the particular service
   296  		ctx := NewServiceContext(n.config, make(map[reflect.Type]Service), n.eventmux, n.accman)
   297  		for kind, s := range services { // copy needed for threaded access
   298  			ctx.services[kind] = s
   299  		}
   300  		// Construct and save the service
   301  		service, err := constructor(ctx)
   302  		if err != nil {
   303  			return err
   304  		}
   305  		kind := reflect.TypeOf(service)
   306  		if _, exists := services[kind]; exists {
   307  			return &DuplicateServiceError{Kind: kind}
   308  		}
   309  		services[kind] = service
   310  	}
   311  	return nil
   312  }
   313  
   314  func (n *Node) openDataDir() error {
   315  	if n.config.DataDir == "" {
   316  		return nil // ephemeral
   317  	}
   318  
   319  	instdir := filepath.Join(n.config.DataDir, n.config.name())
   320  	if err := os.MkdirAll(instdir, 0o700); err != nil {
   321  		return err
   322  	}
   323  
   324  	release, _, err := flock.New(filepath.Join(instdir, "LOCK"))
   325  	if err != nil {
   326  		return convertFileLockError(err)
   327  	}
   328  	n.instanceDirLock = release
   329  	return nil
   330  }
   331  
   332  // startRPC is a helper method to start all the various RPC endpoint during node
   333  // startup. It's not meant to be called at any time afterwards as it makes certain
   334  // assumptions about the state of the node.
   335  func (n *Node) startRPC(services map[reflect.Type]Service) error {
   336  	apis := n.apis()
   337  	for _, service := range services {
   338  		apis = append(apis, service.APIs()...)
   339  	}
   340  	// Start the various API endpoints, terminating all in case of errors
   341  	if err := n.startInProc(apis); err != nil {
   342  		return err
   343  	}
   344  	if err := n.startIPC(apis); err != nil {
   345  		n.stopInProc()
   346  		return err
   347  	}
   348  
   349  	if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors, n.config.HTTPVirtualHosts, n.config.HTTPTimeouts); err != nil {
   350  		n.stopIPC()
   351  		n.stopInProc()
   352  		return err
   353  	}
   354  	if err := n.startWS(n.wsEndpoint, apis, n.config.WSModules, n.config.WSOrigins, n.config.WSExposeAll); err != nil {
   355  		n.stopHTTP()
   356  		n.stopIPC()
   357  		n.stopInProc()
   358  		return err
   359  	}
   360  
   361  	// start gRPC server
   362  	if err := n.startgRPC(apis); err != nil {
   363  		n.stopHTTP()
   364  		n.stopIPC()
   365  		n.stopInProc()
   366  		return err
   367  	}
   368  	// All API endpoints started successfully
   369  	n.rpcAPIs = apis
   370  
   371  	return nil
   372  }
   373  
   374  // startInProc initializes an in-process RPC endpoint.
   375  func (n *Node) startInProc(apis []rpc.API) error {
   376  	// Register all the APIs exposed by the services
   377  	handler := rpc.NewServer()
   378  	for _, api := range apis {
   379  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   380  			return err
   381  		}
   382  		n.logger.Debug("InProc registered", "service", api.Service, "namespace", api.Namespace)
   383  	}
   384  	n.inprocHandler = handler
   385  	return nil
   386  }
   387  
   388  // stopInProc terminates the in-process RPC endpoint.
   389  func (n *Node) stopInProc() {
   390  	if n.inprocHandler != nil {
   391  		n.inprocHandler.Stop()
   392  		n.inprocHandler = nil
   393  	}
   394  }
   395  
   396  // startIPC initializes and starts the IPC RPC endpoint.
   397  func (n *Node) startIPC(apis []rpc.API) error {
   398  	if n.ipcEndpoint == "" {
   399  		return nil // IPC disabled.
   400  	}
   401  	listener, handler, err := rpc.StartIPCEndpoint(n.ipcEndpoint, apis)
   402  	if err != nil {
   403  		return err
   404  	}
   405  	n.ipcListener = listener
   406  	n.ipcHandler = handler
   407  	n.logger.Info("IPC endpoint opened", "url", n.ipcEndpoint)
   408  	return nil
   409  }
   410  
   411  // stopIPC terminates the IPC RPC endpoint.
   412  func (n *Node) stopIPC() {
   413  	if n.ipcListener != nil {
   414  		n.ipcListener.Close()
   415  		n.ipcListener = nil
   416  
   417  		n.logger.Info("IPC endpoint closed", "endpoint", n.ipcEndpoint)
   418  	}
   419  	if n.ipcHandler != nil {
   420  		n.ipcHandler.Stop()
   421  		n.ipcHandler = nil
   422  	}
   423  }
   424  
   425  // startgRPC initializes and starts the gRPC endpoint.
   426  func (n *Node) startgRPC(apis []rpc.API) error {
   427  	if n.grpcEndpoint == "" {
   428  		return nil
   429  	}
   430  
   431  	handler := rpc.NewServer()
   432  	for _, api := range apis {
   433  		if api.Public {
   434  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   435  				return err
   436  			}
   437  			n.logger.Debug("gRPC registered", "namespace", api.Namespace)
   438  		}
   439  	}
   440  
   441  	listener := &grpc.Listener{Addr: n.grpcEndpoint}
   442  	n.grpcHandler = handler
   443  	n.grpcListener = listener
   444  	listener.SetRPCServer(handler)
   445  
   446  	go listener.Start()
   447  	n.logger.Info("gRPC endpoint opened", "url", n.grpcEndpoint)
   448  	return nil
   449  }
   450  
   451  // startHTTP initializes and starts the HTTP RPC endpoint.
   452  func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) error {
   453  	// Short circuit if the HTTP endpoint isn't being exposed
   454  	if endpoint == "" {
   455  		return nil
   456  	}
   457  	listener, handler, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, cors, vhosts, timeouts)
   458  	if err != nil {
   459  		return err
   460  	}
   461  	n.logger.Info("HTTP endpoint opened", "url", fmt.Sprintf("http://%s", endpoint), "cors", strings.Join(cors, ","), "vhosts", strings.Join(vhosts, ","))
   462  	// All listeners booted successfully
   463  	n.httpEndpoint = endpoint
   464  	n.httpListener = listener
   465  	n.httpHandler = handler
   466  
   467  	return nil
   468  }
   469  
   470  // startFastHTTP initializes and starts the HTTP RPC endpoint.
   471  func (n *Node) startFastHTTP(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) error {
   472  	// Short circuit if the HTTP endpoint isn't being exposed
   473  	if endpoint == "" {
   474  		return nil
   475  	}
   476  	listener, handler, err := rpc.StartFastHTTPEndpoint(endpoint, apis, modules, cors, vhosts, timeouts)
   477  	if err != nil {
   478  		return err
   479  	}
   480  	n.logger.Info("FastHTTP endpoint opened", "url", fmt.Sprintf("http://%s", endpoint), "cors", strings.Join(cors, ","), "vhosts", strings.Join(vhosts, ","))
   481  	// All listeners booted successfully
   482  	n.httpEndpoint = endpoint
   483  	n.httpListener = listener
   484  	n.httpHandler = handler
   485  
   486  	return nil
   487  }
   488  
   489  // stopHTTP terminates the HTTP RPC endpoint.
   490  func (n *Node) stopHTTP() {
   491  	if n.httpListener != nil {
   492  		n.httpListener.Close()
   493  		n.httpListener = nil
   494  
   495  		n.logger.Info("HTTP endpoint closed", "url", fmt.Sprintf("http://%s", n.httpEndpoint))
   496  	}
   497  	if n.httpHandler != nil {
   498  		n.httpHandler.Stop()
   499  		n.httpHandler = nil
   500  	}
   501  }
   502  
   503  // startWS initializes and starts the websocket RPC endpoint.
   504  func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrigins []string, exposeAll bool) error {
   505  	// Short circuit if the WS endpoint isn't being exposed
   506  	if endpoint == "" {
   507  		return nil
   508  	}
   509  	listener, handler, err := rpc.StartWSEndpoint(endpoint, apis, modules, wsOrigins, exposeAll)
   510  	if err != nil {
   511  		return err
   512  	}
   513  	n.logger.Info("WebSocket endpoint opened", "url", fmt.Sprintf("ws://%s", listener.Addr()))
   514  	// All listeners booted successfully
   515  	n.wsEndpoint = endpoint
   516  	n.wsListener = listener
   517  	n.wsHandler = handler
   518  
   519  	return nil
   520  }
   521  
   522  // startFastWS initializes and starts the websocket RPC endpoint.
   523  func (n *Node) startFastWS(endpoint string, apis []rpc.API, modules []string, wsOrigins []string, exposeAll bool) error {
   524  	// Short circuit if the WS endpoint isn't being exposed
   525  	if endpoint == "" {
   526  		return nil
   527  	}
   528  	listener, handler, err := rpc.StartFastWSEndpoint(endpoint, apis, modules, wsOrigins, exposeAll)
   529  	if err != nil {
   530  		return err
   531  	}
   532  	n.logger.Info("FastWebSocket endpoint opened", "url", fmt.Sprintf("ws://%s", listener.Addr()))
   533  	// All listeners booted successfully
   534  	n.wsEndpoint = endpoint
   535  	n.wsListener = listener
   536  	n.wsHandler = handler
   537  
   538  	return nil
   539  }
   540  
   541  // stopWS terminates the websocket RPC endpoint.
   542  func (n *Node) stopWS() {
   543  	if n.wsListener != nil {
   544  		n.wsListener.Close()
   545  		n.wsListener = nil
   546  
   547  		n.logger.Info("WebSocket endpoint closed", "url", fmt.Sprintf("ws://%s", n.wsEndpoint))
   548  	}
   549  	if n.wsHandler != nil {
   550  		n.wsHandler.Stop()
   551  		n.wsHandler = nil
   552  	}
   553  }
   554  
   555  func (n *Node) stopgRPC() {
   556  	if n.grpcListener != nil {
   557  		n.grpcListener.Stop()
   558  		n.grpcListener = nil
   559  
   560  		n.logger.Info("gRPC endpoint closed", "url", fmt.Sprintf("grpc://%s", n.grpcEndpoint))
   561  	}
   562  
   563  	if n.grpcHandler != nil {
   564  		n.grpcHandler.Stop()
   565  		n.grpcHandler = nil
   566  	}
   567  }
   568  
   569  // Stop terminates a running node along with all it's services. In the node was
   570  // not started, an error is returned.
   571  func (n *Node) Stop() error {
   572  	n.lock.Lock()
   573  	defer n.lock.Unlock()
   574  
   575  	// Short circuit if the node's not running
   576  	if n.server == nil {
   577  		return ErrNodeStopped
   578  	}
   579  
   580  	// Terminate the API, services and the p2p server.
   581  	n.stopWS()
   582  	n.stopHTTP()
   583  	n.stopIPC()
   584  	n.stopgRPC()
   585  	n.rpcAPIs = nil
   586  	failure := &StopError{
   587  		Services: make(map[reflect.Type]error),
   588  	}
   589  	// subservices are the services which should be terminated before coreservices are terminated.
   590  	for kind, service := range n.subservices {
   591  		if err := service.Stop(); err != nil {
   592  			failure.Services[kind] = err
   593  		}
   594  		// delete the already terminated services.
   595  		delete(n.services, kind)
   596  	}
   597  	for kind, service := range n.services {
   598  		if err := service.Stop(); err != nil {
   599  			failure.Services[kind] = err
   600  		}
   601  	}
   602  	n.server.Stop()
   603  	n.services = nil
   604  	n.server = nil
   605  
   606  	// Release instance directory lock.
   607  	if n.instanceDirLock != nil {
   608  		if err := n.instanceDirLock.Release(); err != nil {
   609  			n.logger.Error("Can't release datadir lock", "err", err)
   610  		}
   611  		n.instanceDirLock = nil
   612  	}
   613  
   614  	// unblock n.Wait
   615  	close(n.stop)
   616  
   617  	// Remove the keystore if it was created ephemerally.
   618  	var keystoreErr error
   619  	if n.ephemeralKeystore != "" {
   620  		keystoreErr = os.RemoveAll(n.ephemeralKeystore)
   621  	}
   622  
   623  	if len(failure.Services) > 0 {
   624  		return failure
   625  	}
   626  	if keystoreErr != nil {
   627  		return keystoreErr
   628  	}
   629  	return nil
   630  }
   631  
   632  // Wait blocks the thread until the node is stopped. If the node is not running
   633  // at the time of invocation, the method immediately returns.
   634  func (n *Node) Wait() {
   635  	n.lock.RLock()
   636  	if n.server == nil {
   637  		n.lock.RUnlock()
   638  		return
   639  	}
   640  	stop := n.stop
   641  	n.lock.RUnlock()
   642  
   643  	<-stop
   644  }
   645  
   646  // Restart terminates a running node and boots up a new one in its place. If the
   647  // node isn't running, an error is returned.
   648  func (n *Node) Restart() error {
   649  	if err := n.Stop(); err != nil {
   650  		return err
   651  	}
   652  	if err := n.Start(); err != nil {
   653  		return err
   654  	}
   655  	return nil
   656  }
   657  
   658  // Attach creates an RPC client attached to an in-process API handler.
   659  func (n *Node) Attach() (*rpc.Client, error) {
   660  	n.lock.RLock()
   661  	defer n.lock.RUnlock()
   662  
   663  	if n.server == nil {
   664  		return nil, ErrNodeStopped
   665  	}
   666  	return rpc.DialInProc(n.inprocHandler), nil
   667  }
   668  
   669  // RPCHandler returns the in-process RPC request handler.
   670  func (n *Node) RPCHandler() (*rpc.Server, error) {
   671  	n.lock.RLock()
   672  	defer n.lock.RUnlock()
   673  
   674  	if n.inprocHandler == nil {
   675  		return nil, ErrNodeStopped
   676  	}
   677  	return n.inprocHandler, nil
   678  }
   679  
   680  // Server retrieves the currently running P2P network layer. This method is meant
   681  // only to inspect fields of the currently running server, life cycle management
   682  // should be left to this Node entity.
   683  func (n *Node) Server() p2p.Server {
   684  	n.lock.RLock()
   685  	defer n.lock.RUnlock()
   686  
   687  	return n.server
   688  }
   689  
   690  // Service retrieves a currently running service registered of a specific type.
   691  func (n *Node) Service(service interface{}) error {
   692  	n.lock.RLock()
   693  	defer n.lock.RUnlock()
   694  
   695  	// Short circuit if the node's not running
   696  	if n.server == nil {
   697  		return ErrNodeStopped
   698  	}
   699  	// Otherwise try to find the service to return
   700  	element := reflect.ValueOf(service).Elem()
   701  	if running, ok := n.services[element.Type()]; ok {
   702  		element.Set(reflect.ValueOf(running))
   703  		return nil
   704  	}
   705  	return ErrServiceUnknown
   706  }
   707  
   708  // DataDir retrieves the current datadir used by the protocol stack.
   709  // Deprecated: No files should be stored in this directory, use InstanceDir instead.
   710  func (n *Node) DataDir() string {
   711  	return n.config.DataDir
   712  }
   713  
   714  // InstanceDir retrieves the instance directory used by the protocol stack.
   715  func (n *Node) InstanceDir() string {
   716  	return n.config.instanceDir()
   717  }
   718  
   719  // AccountManager retrieves the account manager used by the protocol stack.
   720  func (n *Node) AccountManager() *accounts.Manager {
   721  	return n.accman
   722  }
   723  
   724  // IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
   725  func (n *Node) IPCEndpoint() string {
   726  	return n.ipcEndpoint
   727  }
   728  
   729  // HTTPEndpoint retrieves the current HTTP endpoint used by the protocol stack.
   730  func (n *Node) HTTPEndpoint() string {
   731  	return n.httpEndpoint
   732  }
   733  
   734  // WSEndpoint retrieves the current WS endpoint used by the protocol stack.
   735  func (n *Node) WSEndpoint() string {
   736  	return n.wsEndpoint
   737  }
   738  
   739  // EventMux retrieves the event multiplexer used by all the network services in
   740  // the current protocol stack.
   741  func (n *Node) EventMux() *event.TypeMux {
   742  	return n.eventmux
   743  }
   744  
   745  // OpenDatabase opens an existing database with the given name (or creates one if no
   746  // previous can be found) from within the node's instance directory. If the node is
   747  // ephemeral, a memory database is returned.
   748  func (n *Node) OpenDatabase(dbc *database.DBConfig) database.DBManager {
   749  	if n.config.DataDir == "" {
   750  		return database.NewMemoryDBManager()
   751  	}
   752  	dbc.Dir = n.config.ResolvePath(dbc.Dir)
   753  	return database.NewDBManager(dbc)
   754  }
   755  
   756  // ResolvePath returns the absolute path of a resource in the instance directory.
   757  func (n *Node) ResolvePath(x string) string {
   758  	return n.config.ResolvePath(x)
   759  }
   760  
   761  func (n *Node) apis() []rpc.API {
   762  	rpcApi := []rpc.API{
   763  		{
   764  			Namespace: "admin",
   765  			Version:   "1.0",
   766  			Service:   NewPrivateAdminAPI(n),
   767  		}, {
   768  			Namespace: "admin",
   769  			Version:   "1.0",
   770  			Service:   NewPublicAdminAPI(n),
   771  			Public:    true,
   772  		}, {
   773  			Namespace: "debug",
   774  			Version:   "1.0",
   775  			Service:   NewPublicDebugAPI(n),
   776  		}, {
   777  			// "web3" namespace will be deprecated soon. The same APIs in "web3" are available in "klay" namespace.
   778  			Namespace: "web3",
   779  			Version:   "1.0",
   780  			Service:   NewPublicKlayAPI(n),
   781  			Public:    true,
   782  		}, {
   783  			Namespace: "klay",
   784  			Version:   "1.0",
   785  			Service:   NewPublicKlayAPI(n),
   786  			Public:    true,
   787  		},
   788  	}
   789  	debugRpcApi := []rpc.API{
   790  		{
   791  			Namespace: "debug",
   792  			Version:   "1.0",
   793  			Service:   debug.Handler,
   794  		},
   795  	}
   796  	if !n.config.DisableUnsafeDebug {
   797  		rpcApi = append(rpcApi, debugRpcApi...)
   798  	}
   799  	return rpcApi
   800  }
   801  
   802  const (
   803  	ntpTolerance = time.Second
   804  	RFC3339Nano  = "2006-01-02T15:04:05.999999999Z07:00"
   805  	ntpMaxRetry  = 10
   806  )
   807  
   808  func timeIsNear(lhs, rhs time.Time) bool {
   809  	diff := lhs.Sub(rhs)
   810  	// TODO: use time.Duration.Abs() after go1.19
   811  	if diff < 0 {
   812  		diff = -diff
   813  	}
   814  	return diff < ntpTolerance
   815  }
   816  
   817  func NtpCheckWithLocal(n *Node) error {
   818  	// Skip check if server is empty (e.g. `ntp.disable` flag)
   819  	if n.config.NtpRemoteServer == "" {
   820  		return nil
   821  	}
   822  
   823  	url, port, err := net.SplitHostPort(n.config.NtpRemoteServer)
   824  	if err != nil {
   825  		return err
   826  	}
   827  	portNum, err := strconv.Atoi(port)
   828  	if err != nil {
   829  		return err
   830  	}
   831  
   832  	ntpRetryTime := time.Duration(1)
   833  	var remote *time.Time
   834  	for i := 0; i < ntpMaxRetry; i++ {
   835  		time.Sleep(ntpRetryTime)
   836  		remote, err = ntpclient.GetNetworkTime(url, portNum)
   837  		if remote != nil {
   838  			break
   839  		}
   840  		ntpRetryTime = ntpRetryTime * 2
   841  	}
   842  	if err != nil {
   843  		return err
   844  	}
   845  
   846  	local := time.Now()
   847  	if !timeIsNear(local, *remote) {
   848  		errFormat := "System time is out of sync, local:%s remote:%s"
   849  		usage := "You can use \"--ntp.disable\" option to disable ntp time checking"
   850  		return fmt.Errorf(errFormat+"\n"+usage, local.UTC().Format(RFC3339Nano), remote.UTC().Format(RFC3339Nano))
   851  	}
   852  	logger.Info("Ntp time check", "local", local.UTC().Format(RFC3339Nano), "remote", remote.UTC().Format(RFC3339Nano))
   853  	return nil
   854  }