node.go 20 KB

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