github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/node/node.go (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package node
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"net"
    23  	"os"
    24  	"path/filepath"
    25  	"reflect"
    26  	"strings"
    27  	"sync"
    28  
    29  	"github.com/SmartMeshFoundation/Spectrum/accounts"
    30  	"github.com/SmartMeshFoundation/Spectrum/ethdb"
    31  	"github.com/SmartMeshFoundation/Spectrum/event"
    32  	"github.com/SmartMeshFoundation/Spectrum/internal/debug"
    33  	"github.com/SmartMeshFoundation/Spectrum/log"
    34  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    35  	"github.com/SmartMeshFoundation/Spectrum/rpc"
    36  
    37  	//"github.com/cc14514/smc-devnet/lib"
    38  	"github.com/SmartMeshFoundation/Spectrum/internal/smc-devnet/lib"
    39  	"github.com/prometheus/prometheus/util/flock"
    40  )
    41  
    42  // Node is a container on which services can be registered.
    43  type Node struct {
    44  	eventmux *event.TypeMux // Event multiplexer used between the services of a stack
    45  	config   *Config
    46  	accman   *accounts.Manager
    47  
    48  	ephemeralKeystore string         // if non-empty, the key directory that will be removed by Stop
    49  	instanceDirLock   flock.Releaser // prevents concurrent use of instance directory
    50  
    51  	serverConfig p2p.Config
    52  	server       *p2p.Server // Currently running P2P networking layer
    53  
    54  	serviceFuncs []ServiceConstructor     // Service constructors (in dependency order)
    55  	services     map[reflect.Type]Service // Currently running services
    56  
    57  	rpcAPIs       []rpc.API   // List of APIs currently provided by the node
    58  	inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
    59  
    60  	ipcEndpoint string       // IPC endpoint to listen at (empty = IPC disabled)
    61  	ipcListener net.Listener // IPC RPC listener socket to serve API requests
    62  	ipcHandler  *rpc.Server  // IPC RPC request handler to process the API requests
    63  
    64  	httpEndpoint  string       // HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
    65  	httpWhitelist []string     // HTTP RPC modules to allow through this endpoint
    66  	httpListener  net.Listener // HTTP RPC listener socket to server API requests
    67  	httpHandler   *rpc.Server  // HTTP RPC request handler to process the API requests
    68  
    69  	wsEndpoint string       // Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
    70  	wsListener net.Listener // Websocket RPC listener socket to server API requests
    71  	wsHandler  *rpc.Server  // Websocket RPC request handler to process the API requests
    72  
    73  	stop chan struct{} // Channel to wait for termination notifications
    74  	lock sync.RWMutex
    75  
    76  	log log.Logger
    77  }
    78  
    79  // New creates a new P2P node, ready for protocol registration.
    80  func New(conf *Config) (*Node, error) {
    81  	// Copy config and resolve the datadir so future changes to the current
    82  	// working directory don't affect the node.
    83  	confCopy := *conf
    84  	conf = &confCopy
    85  	if conf.DataDir != "" {
    86  		absdatadir, err := filepath.Abs(conf.DataDir)
    87  		if err != nil {
    88  			return nil, err
    89  		}
    90  		conf.DataDir = absdatadir
    91  	}
    92  	// Ensure that the instance name doesn't cause weird conflicts with
    93  	// other files in the data directory.
    94  	if strings.ContainsAny(conf.Name, `/\`) {
    95  		return nil, errors.New(`Config.Name must not contain '/' or '\'`)
    96  	}
    97  	if conf.Name == datadirDefaultKeyStore {
    98  		return nil, errors.New(`Config.Name cannot be "` + datadirDefaultKeyStore + `"`)
    99  	}
   100  	if strings.HasSuffix(conf.Name, ".ipc") {
   101  		return nil, errors.New(`Config.Name cannot end in ".ipc"`)
   102  	}
   103  	// Ensure that the AccountManager method works before the node has started.
   104  	// We rely on this in cmd/geth.
   105  	am, ephemeralKeystore, err := makeAccountManager(conf)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	if conf.Logger == nil {
   110  		conf.Logger = log.New()
   111  	}
   112  	// Note: any interaction with Config that would create/touch files
   113  	// in the data directory or instance directory is delayed until Start.
   114  	return &Node{
   115  		accman:            am,
   116  		ephemeralKeystore: ephemeralKeystore,
   117  		config:            conf,
   118  		serviceFuncs:      []ServiceConstructor{},
   119  		ipcEndpoint:       conf.IPCEndpoint(),
   120  		httpEndpoint:      conf.HTTPEndpoint(),
   121  		wsEndpoint:        conf.WSEndpoint(),
   122  		eventmux:          new(event.TypeMux),
   123  		log:               conf.Logger,
   124  	}, nil
   125  }
   126  
   127  // Register injects a new service into the node's stack. The service created by
   128  // the passed constructor must be unique in its type with regard to sibling ones.
   129  func (n *Node) Register(constructor ServiceConstructor) error {
   130  	n.lock.Lock()
   131  	defer n.lock.Unlock()
   132  
   133  	if n.server != nil {
   134  		return ErrNodeRunning
   135  	}
   136  	n.serviceFuncs = append(n.serviceFuncs, constructor)
   137  	return nil
   138  }
   139  
   140  // Start create a live P2P node and starts running it.
   141  func (n *Node) Start() error {
   142  	n.lock.Lock()
   143  	defer n.lock.Unlock()
   144  
   145  	// Short circuit if the node's already running
   146  	if n.server != nil {
   147  		return ErrNodeRunning
   148  	}
   149  	if err := n.openDataDir(); err != nil {
   150  		return err
   151  	}
   152  
   153  	// Initialize the p2p server. This creates the node key and
   154  	// discovery databases.
   155  	n.serverConfig = n.config.P2P
   156  	n.serverConfig.PrivateKey = n.config.NodeKey()
   157  	n.serverConfig.Name = n.config.NodeName()
   158  	n.serverConfig.Logger = n.log
   159  	if n.serverConfig.StaticNodes == nil {
   160  		n.serverConfig.StaticNodes = n.config.StaticNodes()
   161  	}
   162  	if n.serverConfig.TrustedNodes == nil {
   163  		n.serverConfig.TrustedNodes = n.config.TrustedNodes()
   164  	}
   165  	if n.serverConfig.NodeDatabase == "" {
   166  		n.serverConfig.NodeDatabase = n.config.NodeDB()
   167  	}
   168  	running := &p2p.Server{Config: n.serverConfig}
   169  	n.log.Info("Starting peer-to-peer node", "instance", n.serverConfig.Name)
   170  
   171  	// Otherwise copy and specialize the P2P configuration
   172  	services := make(map[reflect.Type]Service)
   173  	for _, constructor := range n.serviceFuncs {
   174  		// Create a new context for the particular service
   175  		ctx := &ServiceContext{
   176  			config:         n.config,
   177  			services:       make(map[reflect.Type]Service),
   178  			EventMux:       n.eventmux,
   179  			AccountManager: n.accman,
   180  		}
   181  		for kind, s := range services { // copy needed for threaded access
   182  			ctx.services[kind] = s
   183  		}
   184  		// Construct and save the service
   185  		service, err := constructor(ctx)
   186  		if err != nil {
   187  			return err
   188  		}
   189  		kind := reflect.TypeOf(service)
   190  		if _, exists := services[kind]; exists {
   191  			return &DuplicateServiceError{Kind: kind}
   192  		}
   193  		services[kind] = service
   194  	}
   195  	// Gather the protocols and start the freshly assembled P2P server
   196  	for _, service := range services {
   197  		running.Protocols = append(running.Protocols, service.Protocols()...)
   198  	}
   199  
   200  	if err := running.Start(); err != nil {
   201  		return convertFileLockError(err)
   202  	}
   203  	// Start each of the services
   204  	started := []reflect.Type{}
   205  	for kind, service := range services {
   206  		// Start the next service, stopping all previous upon failure
   207  		if err := service.Start(running); err != nil {
   208  			for _, kind := range started {
   209  				services[kind].Stop()
   210  			}
   211  			running.Stop()
   212  
   213  			return err
   214  		}
   215  		// Mark the service started for potential cleanup
   216  		started = append(started, kind)
   217  	}
   218  	// Lastly start the configured RPC interfaces
   219  	if err := n.startRPC(services); err != nil {
   220  		for _, service := range services {
   221  			service.Stop()
   222  		}
   223  		running.Stop()
   224  		return err
   225  	}
   226  	// Finish initializing the startup
   227  	n.services = services
   228  	n.server = running
   229  	n.stop = make(chan struct{})
   230  
   231  	return nil
   232  }
   233  
   234  func (n *Node) openDataDir() error {
   235  	if n.config.DataDir == "" {
   236  		return nil // ephemeral
   237  	}
   238  
   239  	instdir := filepath.Join(n.config.DataDir, n.config.name())
   240  
   241  	if n.config.Devnet {
   242  		if n.config.DevReset {
   243  			os.RemoveAll(instdir)
   244  		}
   245  		if n.config.DevMaster && n.config.DevReset {
   246  			if f, err := os.Open(instdir); err != nil {
   247  				if _, err := lib.Restore(n.config.DataDir, n.config.DevReset, n.config.DevMaster); err != nil {
   248  					panic(err)
   249  				}
   250  			} else {
   251  				f.Close()
   252  			}
   253  		}
   254  	}
   255  
   256  	if err := os.MkdirAll(instdir, 0700); err != nil {
   257  		return err
   258  	}
   259  
   260  	// Lock the instance directory to prevent concurrent use by another instance as well as
   261  	// accidental use of the instance directory as a database.
   262  	release, _, err := flock.New(filepath.Join(instdir, "LOCK"))
   263  	if err != nil {
   264  		return convertFileLockError(err)
   265  	}
   266  	n.instanceDirLock = release
   267  	return nil
   268  }
   269  
   270  // startRPC is a helper method to start all the various RPC endpoint during node
   271  // startup. It's not meant to be called at any time afterwards as it makes certain
   272  // assumptions about the state of the node.
   273  func (n *Node) startRPC(services map[reflect.Type]Service) error {
   274  	// Gather all the possible APIs to surface
   275  	apis := n.apis()
   276  	for _, service := range services {
   277  		apis = append(apis, service.APIs()...)
   278  	}
   279  	// Start the various API endpoints, terminating all in case of errors
   280  	if err := n.startInProc(apis); err != nil {
   281  		return err
   282  	}
   283  	if err := n.startIPC(apis); err != nil {
   284  		n.stopInProc()
   285  		return err
   286  	}
   287  	if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors); err != nil {
   288  		n.stopIPC()
   289  		n.stopInProc()
   290  		return err
   291  	}
   292  	if err := n.startWS(n.wsEndpoint, apis, n.config.WSModules, n.config.WSOrigins, n.config.WSExposeAll); err != nil {
   293  		n.stopHTTP()
   294  		n.stopIPC()
   295  		n.stopInProc()
   296  		return err
   297  	}
   298  	// All API endpoints started successfully
   299  	n.rpcAPIs = apis
   300  	return nil
   301  }
   302  
   303  // startInProc initializes an in-process RPC endpoint.
   304  func (n *Node) startInProc(apis []rpc.API) error {
   305  	// Register all the APIs exposed by the services
   306  	handler := rpc.NewServer()
   307  	for _, api := range apis {
   308  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   309  			return err
   310  		}
   311  		n.log.Debug(fmt.Sprintf("InProc registered %T under '%s'", api.Service, api.Namespace))
   312  	}
   313  	n.inprocHandler = handler
   314  	return nil
   315  }
   316  
   317  // stopInProc terminates the in-process RPC endpoint.
   318  func (n *Node) stopInProc() {
   319  	if n.inprocHandler != nil {
   320  		n.inprocHandler.Stop()
   321  		n.inprocHandler = nil
   322  	}
   323  }
   324  
   325  // startIPC initializes and starts the IPC RPC endpoint.
   326  func (n *Node) startIPC(apis []rpc.API) error {
   327  	// Short circuit if the IPC endpoint isn't being exposed
   328  	if n.ipcEndpoint == "" {
   329  		return nil
   330  	}
   331  	// Register all the APIs exposed by the services
   332  	handler := rpc.NewServer()
   333  	for _, api := range apis {
   334  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   335  			return err
   336  		}
   337  		n.log.Debug(fmt.Sprintf("IPC registered %T under '%s'", api.Service, api.Namespace))
   338  	}
   339  	// All APIs registered, start the IPC listener
   340  	var (
   341  		listener net.Listener
   342  		err      error
   343  	)
   344  	if listener, err = rpc.CreateIPCListener(n.ipcEndpoint); err != nil {
   345  		return err
   346  	}
   347  	go func() {
   348  		n.log.Info(fmt.Sprintf("IPC endpoint opened: %s", n.ipcEndpoint))
   349  
   350  		for {
   351  			conn, err := listener.Accept()
   352  			if err != nil {
   353  				// Terminate if the listener was closed
   354  				n.lock.RLock()
   355  				closed := n.ipcListener == nil
   356  				n.lock.RUnlock()
   357  				if closed {
   358  					return
   359  				}
   360  				// Not closed, just some error; report and continue
   361  				n.log.Error(fmt.Sprintf("IPC accept failed: %v", err))
   362  				continue
   363  			}
   364  			go handler.ServeCodec(rpc.NewJSONCodec(conn), rpc.OptionMethodInvocation|rpc.OptionSubscriptions)
   365  		}
   366  	}()
   367  	// All listeners booted successfully
   368  	n.ipcListener = listener
   369  	n.ipcHandler = handler
   370  
   371  	return nil
   372  }
   373  
   374  // stopIPC terminates the IPC RPC endpoint.
   375  func (n *Node) stopIPC() {
   376  	if n.ipcListener != nil {
   377  		n.ipcListener.Close()
   378  		n.ipcListener = nil
   379  
   380  		n.log.Info(fmt.Sprintf("IPC endpoint closed: %s", n.ipcEndpoint))
   381  	}
   382  	if n.ipcHandler != nil {
   383  		n.ipcHandler.Stop()
   384  		n.ipcHandler = nil
   385  	}
   386  }
   387  
   388  // startHTTP initializes and starts the HTTP RPC endpoint.
   389  func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string) error {
   390  	// Short circuit if the HTTP endpoint isn't being exposed
   391  	if endpoint == "" {
   392  		return nil
   393  	}
   394  	// Generate the whitelist based on the allowed modules
   395  	whitelist := make(map[string]bool)
   396  	for _, module := range modules {
   397  		whitelist[module] = true
   398  	}
   399  	// Register all the APIs exposed by the services
   400  	handler := rpc.NewServer()
   401  	for _, api := range apis {
   402  		if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
   403  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   404  				return err
   405  			}
   406  			n.log.Debug(fmt.Sprintf("HTTP registered %T under '%s'", api.Service, api.Namespace))
   407  		}
   408  	}
   409  	// All APIs registered, start the HTTP listener
   410  	var (
   411  		listener net.Listener
   412  		err      error
   413  	)
   414  	if listener, err = net.Listen("tcp", endpoint); err != nil {
   415  		return err
   416  	}
   417  	go rpc.NewHTTPServer(cors, handler).Serve(listener)
   418  	n.log.Info(fmt.Sprintf("HTTP endpoint opened: http://%s", endpoint))
   419  
   420  	// All listeners booted successfully
   421  	n.httpEndpoint = endpoint
   422  	n.httpListener = listener
   423  	n.httpHandler = handler
   424  
   425  	return nil
   426  }
   427  
   428  // stopHTTP terminates the HTTP RPC endpoint.
   429  func (n *Node) stopHTTP() {
   430  	if n.httpListener != nil {
   431  		n.httpListener.Close()
   432  		n.httpListener = nil
   433  
   434  		n.log.Info(fmt.Sprintf("HTTP endpoint closed: http://%s", n.httpEndpoint))
   435  	}
   436  	if n.httpHandler != nil {
   437  		n.httpHandler.Stop()
   438  		n.httpHandler = nil
   439  	}
   440  }
   441  
   442  // startWS initializes and starts the websocket RPC endpoint.
   443  func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrigins []string, exposeAll bool) error {
   444  	// Short circuit if the WS endpoint isn't being exposed
   445  	if endpoint == "" {
   446  		return nil
   447  	}
   448  	// Generate the whitelist based on the allowed modules
   449  	whitelist := make(map[string]bool)
   450  	for _, module := range modules {
   451  		whitelist[module] = true
   452  	}
   453  	// Register all the APIs exposed by the services
   454  	handler := rpc.NewServer()
   455  	for _, api := range apis {
   456  		if exposeAll || whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
   457  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   458  				return err
   459  			}
   460  			n.log.Debug(fmt.Sprintf("WebSocket registered %T under '%s'", api.Service, api.Namespace))
   461  		}
   462  	}
   463  	// All APIs registered, start the HTTP listener
   464  	var (
   465  		listener net.Listener
   466  		err      error
   467  	)
   468  	if listener, err = net.Listen("tcp", endpoint); err != nil {
   469  		return err
   470  	}
   471  	go rpc.NewWSServer(wsOrigins, handler).Serve(listener)
   472  	n.log.Info(fmt.Sprintf("WebSocket endpoint opened: ws://%s", listener.Addr()))
   473  
   474  	// All listeners booted successfully
   475  	n.wsEndpoint = endpoint
   476  	n.wsListener = listener
   477  	n.wsHandler = handler
   478  
   479  	return nil
   480  }
   481  
   482  // stopWS terminates the websocket RPC endpoint.
   483  func (n *Node) stopWS() {
   484  	if n.wsListener != nil {
   485  		n.wsListener.Close()
   486  		n.wsListener = nil
   487  
   488  		n.log.Info(fmt.Sprintf("WebSocket endpoint closed: ws://%s", n.wsEndpoint))
   489  	}
   490  	if n.wsHandler != nil {
   491  		n.wsHandler.Stop()
   492  		n.wsHandler = nil
   493  	}
   494  }
   495  
   496  // Stop terminates a running node along with all it's services. In the node was
   497  // not started, an error is returned.
   498  func (n *Node) Stop() error {
   499  	n.lock.Lock()
   500  	defer n.lock.Unlock()
   501  
   502  	// Short circuit if the node's not running
   503  	if n.server == nil {
   504  		return ErrNodeStopped
   505  	}
   506  
   507  	// Terminate the API, services and the p2p server.
   508  	n.stopWS()
   509  	n.stopHTTP()
   510  	n.stopIPC()
   511  	n.rpcAPIs = nil
   512  	failure := &StopError{
   513  		Services: make(map[reflect.Type]error),
   514  	}
   515  	for kind, service := range n.services {
   516  		if err := service.Stop(); err != nil {
   517  			failure.Services[kind] = err
   518  		}
   519  	}
   520  	n.server.Stop()
   521  	n.services = nil
   522  	n.server = nil
   523  
   524  	// Release instance directory lock.
   525  	if n.instanceDirLock != nil {
   526  		if err := n.instanceDirLock.Release(); err != nil {
   527  			n.log.Error("Can't release datadir lock", "err", err)
   528  		}
   529  		n.instanceDirLock = nil
   530  	}
   531  
   532  	// unblock n.Wait
   533  	close(n.stop)
   534  
   535  	// Remove the keystore if it was created ephemerally.
   536  	var keystoreErr error
   537  	if n.ephemeralKeystore != "" {
   538  		keystoreErr = os.RemoveAll(n.ephemeralKeystore)
   539  	}
   540  
   541  	if len(failure.Services) > 0 {
   542  		return failure
   543  	}
   544  	if keystoreErr != nil {
   545  		return keystoreErr
   546  	}
   547  	return nil
   548  }
   549  
   550  // Wait blocks the thread until the node is stopped. If the node is not running
   551  // at the time of invocation, the method immediately returns.
   552  func (n *Node) Wait() {
   553  	n.lock.RLock()
   554  	if n.server == nil {
   555  		n.lock.RUnlock()
   556  		return
   557  	}
   558  	stop := n.stop
   559  	n.lock.RUnlock()
   560  
   561  	<-stop
   562  }
   563  
   564  // Restart terminates a running node and boots up a new one in its place. If the
   565  // node isn't running, an error is returned.
   566  func (n *Node) Restart() error {
   567  	if err := n.Stop(); err != nil {
   568  		return err
   569  	}
   570  	if err := n.Start(); err != nil {
   571  		return err
   572  	}
   573  	return nil
   574  }
   575  
   576  // Attach creates an RPC client attached to an in-process API handler.
   577  func (n *Node) Attach() (*rpc.Client, error) {
   578  	n.lock.RLock()
   579  	defer n.lock.RUnlock()
   580  
   581  	if n.server == nil {
   582  		return nil, ErrNodeStopped
   583  	}
   584  	return rpc.DialInProc(n.inprocHandler), nil
   585  }
   586  
   587  // RPCHandler returns the in-process RPC request handler.
   588  func (n *Node) RPCHandler() (*rpc.Server, error) {
   589  	n.lock.RLock()
   590  	defer n.lock.RUnlock()
   591  
   592  	if n.inprocHandler == nil {
   593  		return nil, ErrNodeStopped
   594  	}
   595  	return n.inprocHandler, nil
   596  }
   597  
   598  // Server retrieves the currently running P2P network layer. This method is meant
   599  // only to inspect fields of the currently running server, life cycle management
   600  // should be left to this Node entity.
   601  func (n *Node) Server() *p2p.Server {
   602  	n.lock.RLock()
   603  	defer n.lock.RUnlock()
   604  
   605  	return n.server
   606  }
   607  
   608  // Service retrieves a currently running service registered of a specific type.
   609  func (n *Node) Service(service interface{}) error {
   610  	n.lock.RLock()
   611  	defer n.lock.RUnlock()
   612  
   613  	// Short circuit if the node's not running
   614  	if n.server == nil {
   615  		return ErrNodeStopped
   616  	}
   617  	// Otherwise try to find the service to return
   618  	element := reflect.ValueOf(service).Elem()
   619  	if running, ok := n.services[element.Type()]; ok {
   620  		element.Set(reflect.ValueOf(running))
   621  		return nil
   622  	}
   623  	return ErrServiceUnknown
   624  }
   625  
   626  // DataDir retrieves the current datadir used by the protocol stack.
   627  // Deprecated: No files should be stored in this directory, use InstanceDir instead.
   628  func (n *Node) DataDir() string {
   629  	return n.config.DataDir
   630  }
   631  
   632  // InstanceDir retrieves the instance directory used by the protocol stack.
   633  func (n *Node) InstanceDir() string {
   634  	return n.config.instanceDir()
   635  }
   636  
   637  // AccountManager retrieves the account manager used by the protocol stack.
   638  func (n *Node) AccountManager() *accounts.Manager {
   639  	return n.accman
   640  }
   641  
   642  // IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
   643  func (n *Node) IPCEndpoint() string {
   644  	return n.ipcEndpoint
   645  }
   646  
   647  // HTTPEndpoint retrieves the current HTTP endpoint used by the protocol stack.
   648  func (n *Node) HTTPEndpoint() string {
   649  	return n.httpEndpoint
   650  }
   651  
   652  // WSEndpoint retrieves the current WS endpoint used by the protocol stack.
   653  func (n *Node) WSEndpoint() string {
   654  	return n.wsEndpoint
   655  }
   656  
   657  // EventMux retrieves the event multiplexer used by all the network services in
   658  // the current protocol stack.
   659  func (n *Node) EventMux() *event.TypeMux {
   660  	return n.eventmux
   661  }
   662  
   663  // OpenDatabase opens an existing database with the given name (or creates one if no
   664  // previous can be found) from within the node's instance directory. If the node is
   665  // ephemeral, a memory database is returned.
   666  func (n *Node) OpenDatabase(name string, cache, handles int) (ethdb.Database, error) {
   667  	if n.config.DataDir == "" {
   668  		return ethdb.NewMemDatabase()
   669  	}
   670  	return ethdb.NewLDBDatabase(n.config.resolvePath(name), cache, handles)
   671  }
   672  
   673  // ResolvePath returns the absolute path of a resource in the instance directory.
   674  func (n *Node) ResolvePath(x string) string {
   675  	return n.config.resolvePath(x)
   676  }
   677  
   678  // apis returns the collection of RPC descriptors this node offers.
   679  func (n *Node) apis() []rpc.API {
   680  	return []rpc.API{
   681  		{
   682  			Namespace: "admin",
   683  			Version:   "1.0",
   684  			Service:   NewPrivateAdminAPI(n),
   685  		}, {
   686  			Namespace: "admin",
   687  			Version:   "1.0",
   688  			Service:   NewPublicAdminAPI(n),
   689  			Public:    true,
   690  		}, {
   691  			Namespace: "debug",
   692  			Version:   "1.0",
   693  			Service:   debug.Handler,
   694  		}, {
   695  			Namespace: "debug",
   696  			Version:   "1.0",
   697  			Service:   NewPublicDebugAPI(n),
   698  			Public:    true,
   699  		}, {
   700  			Namespace: "web3",
   701  			Version:   "1.0",
   702  			Service:   NewPublicWeb3API(n),
   703  			Public:    true,
   704  		},
   705  	}
   706  }