node.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  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. "crypto/ecdsa"
  19. "errors"
  20. "fmt"
  21. "net/http"
  22. "os"
  23. "path/filepath"
  24. "reflect"
  25. "strings"
  26. "sync"
  27. "github.com/ethereum/go-ethereum/accounts"
  28. "github.com/ethereum/go-ethereum/core/rawdb"
  29. "github.com/ethereum/go-ethereum/core/types"
  30. "github.com/ethereum/go-ethereum/ethdb"
  31. "github.com/ethereum/go-ethereum/event"
  32. "github.com/ethereum/go-ethereum/log"
  33. "github.com/ethereum/go-ethereum/p2p"
  34. "github.com/ethereum/go-ethereum/plugin"
  35. "github.com/ethereum/go-ethereum/plugin/security"
  36. "github.com/ethereum/go-ethereum/rpc"
  37. "github.com/prometheus/tsdb/fileutil"
  38. )
  39. // Node is a container on which services can be registered.
  40. type Node struct {
  41. eventmux *event.TypeMux
  42. config *Config
  43. accman *accounts.Manager
  44. log log.Logger
  45. ephemKeystore string // if non-empty, the key directory that will be removed by Stop
  46. dirLock fileutil.Releaser // prevents concurrent use of instance directory
  47. stop chan struct{} // Channel to wait for termination notifications
  48. server *p2p.Server // Currently running P2P networking layer
  49. qserver *p2p.Server // Currently running P2P networking layer for QLight
  50. startStopLock sync.Mutex // Start/Stop are protected by an additional lock
  51. state int // Tracks state of node lifecycle
  52. lock sync.Mutex
  53. lifecycles []Lifecycle // All registered backends, services, and auxiliary services that have a lifecycle
  54. rpcAPIs []rpc.API // List of APIs currently provided by the node
  55. http *httpServer //
  56. ws *httpServer //
  57. ipc *ipcServer // Stores information about the ipc http server
  58. inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
  59. databases map[*closeTrackingDB]struct{} // All open databases
  60. // Quorum
  61. pluginManager *plugin.PluginManager // Manage all plugins for this node. If plugin is not enabled, an EmptyPluginManager is set.
  62. // End Quorum
  63. }
  64. const (
  65. initializingState = iota
  66. runningState
  67. closedState
  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. if conf.Logger == nil {
  83. conf.Logger = log.New()
  84. }
  85. // Ensure that the instance name doesn't cause weird conflicts with
  86. // other files in the data directory.
  87. if strings.ContainsAny(conf.Name, `/\`) {
  88. return nil, errors.New(`Config.Name must not contain '/' or '\'`)
  89. }
  90. if conf.Name == datadirDefaultKeyStore {
  91. return nil, errors.New(`Config.Name cannot be "` + datadirDefaultKeyStore + `"`)
  92. }
  93. if strings.HasSuffix(conf.Name, ".ipc") {
  94. return nil, errors.New(`Config.Name cannot end in ".ipc"`)
  95. }
  96. node := &Node{
  97. config: conf,
  98. inprocHandler: rpc.NewProtectedServer(nil, conf.EnableMultitenancy),
  99. eventmux: new(event.TypeMux),
  100. log: conf.Logger,
  101. stop: make(chan struct{}),
  102. server: &p2p.Server{Config: conf.P2P},
  103. databases: make(map[*closeTrackingDB]struct{}),
  104. pluginManager: plugin.NewEmptyPluginManager(),
  105. }
  106. if conf.QP2P != nil {
  107. node.qserver = &p2p.Server{Config: *conf.QP2P}
  108. }
  109. // Register built-in APIs.
  110. node.rpcAPIs = append(node.rpcAPIs, node.apis()...)
  111. // Acquire the instance directory lock.
  112. if err := node.openDataDir(); err != nil {
  113. return nil, err
  114. }
  115. // Ensure that the AccountManager method works before the node has started. We rely on
  116. // this in cmd/geth.
  117. am, ephemeralKeystore, err := makeAccountManager(conf)
  118. if err != nil {
  119. return nil, err
  120. }
  121. node.accman = am
  122. node.ephemKeystore = ephemeralKeystore
  123. // Initialize the p2p server. This creates the node key and discovery databases.
  124. node.server.Config.PrivateKey = node.config.NodeKey()
  125. node.server.Config.Name = node.config.NodeName()
  126. node.server.Config.Logger = node.log
  127. if node.server.Config.StaticNodes == nil {
  128. node.server.Config.StaticNodes = node.config.StaticNodes()
  129. }
  130. if node.server.Config.TrustedNodes == nil {
  131. node.server.Config.TrustedNodes = node.config.TrustedNodes()
  132. }
  133. if node.server.Config.NodeDatabase == "" {
  134. node.server.Config.NodeDatabase = node.config.NodeDB()
  135. }
  136. if node.qserver != nil {
  137. node.qserver.Config.PrivateKey = node.config.NodeKey()
  138. node.qserver.Config.Name = "qgeth"
  139. node.qserver.Config.Logger = node.log
  140. node.qserver.Config.NodeDatabase = node.config.QNodeDB()
  141. node.qserver.Config.DataDir = node.config.DataDir
  142. }
  143. // Check HTTP/WS prefixes are valid.
  144. if err := validatePrefix("HTTP", conf.HTTPPathPrefix); err != nil {
  145. return nil, err
  146. }
  147. if err := validatePrefix("WebSocket", conf.WSPathPrefix); err != nil {
  148. return nil, err
  149. }
  150. // Quorum
  151. node.server.Config.EnableNodePermission = node.config.EnableNodePermission
  152. node.server.Config.DataDir = node.config.DataDir
  153. // End Quorum
  154. // Check HTTP/WS prefixes are valid.
  155. if err := validatePrefix("HTTP", conf.HTTPPathPrefix); err != nil {
  156. return nil, err
  157. }
  158. if err := validatePrefix("WebSocket", conf.WSPathPrefix); err != nil {
  159. return nil, err
  160. }
  161. // Configure RPC servers.
  162. node.http = newHTTPServer(node.log, conf.HTTPTimeouts).withMultitenancy(node.config.EnableMultitenancy)
  163. node.ws = newHTTPServer(node.log, rpc.DefaultHTTPTimeouts).withMultitenancy(node.config.EnableMultitenancy)
  164. node.ipc = newIPCServer(node.log, conf.IPCEndpoint()).withMultitenancy(node.config.EnableMultitenancy)
  165. return node, nil
  166. }
  167. // Start starts all registered lifecycles, RPC services and p2p networking.
  168. // Node can only be started once.
  169. func (n *Node) Start() error {
  170. n.startStopLock.Lock()
  171. defer n.startStopLock.Unlock()
  172. n.lock.Lock()
  173. switch n.state {
  174. case runningState:
  175. n.lock.Unlock()
  176. return ErrNodeRunning
  177. case closedState:
  178. n.lock.Unlock()
  179. return ErrNodeStopped
  180. }
  181. n.state = runningState
  182. // Quorum
  183. // Start the plugin manager before as might be needed for TLS and Auth manager for networking/rpc.
  184. if err := n.PluginManager().Start(); err != nil {
  185. n.doClose(nil)
  186. return err
  187. }
  188. // End Quorum
  189. // open networking and RPC endpoints
  190. err := n.openEndpoints()
  191. lifecycles := make([]Lifecycle, len(n.lifecycles))
  192. copy(lifecycles, n.lifecycles)
  193. n.lock.Unlock()
  194. // Check if endpoint startup failed.
  195. if err != nil {
  196. n.doClose(nil)
  197. return err
  198. }
  199. // Start all registered lifecycles.
  200. var started []Lifecycle
  201. for _, lifecycle := range lifecycles {
  202. if err = lifecycle.Start(); err != nil {
  203. break
  204. }
  205. started = append(started, lifecycle)
  206. }
  207. // Check if any lifecycle failed to start.
  208. if err != nil {
  209. n.stopServices(started)
  210. n.doClose(nil)
  211. }
  212. return err
  213. }
  214. // Close stops the Node and releases resources acquired in
  215. // Node constructor New.
  216. func (n *Node) Close() error {
  217. n.startStopLock.Lock()
  218. defer n.startStopLock.Unlock()
  219. n.lock.Lock()
  220. state := n.state
  221. n.lock.Unlock()
  222. switch state {
  223. case initializingState:
  224. // The node was never started.
  225. return n.doClose(nil)
  226. case runningState:
  227. // The node was started, release resources acquired by Start().
  228. var errs []error
  229. if err := n.stopServices(n.lifecycles); err != nil {
  230. errs = append(errs, err)
  231. }
  232. return n.doClose(errs)
  233. case closedState:
  234. return ErrNodeStopped
  235. default:
  236. panic(fmt.Sprintf("node is in unknown state %d", state))
  237. }
  238. }
  239. // doClose releases resources acquired by New(), collecting errors.
  240. func (n *Node) doClose(errs []error) error {
  241. // Close databases. This needs the lock because it needs to
  242. // synchronize with OpenDatabase*.
  243. n.lock.Lock()
  244. n.state = closedState
  245. errs = append(errs, n.closeDatabases()...)
  246. n.lock.Unlock()
  247. if err := n.accman.Close(); err != nil {
  248. errs = append(errs, err)
  249. }
  250. if n.ephemKeystore != "" {
  251. if err := os.RemoveAll(n.ephemKeystore); err != nil {
  252. errs = append(errs, err)
  253. }
  254. }
  255. // Release instance directory lock.
  256. n.closeDataDir()
  257. // Unblock n.Wait.
  258. close(n.stop)
  259. // Report any errors that might have occurred.
  260. switch len(errs) {
  261. case 0:
  262. return nil
  263. case 1:
  264. return errs[0]
  265. default:
  266. return fmt.Errorf("%v", errs)
  267. }
  268. }
  269. // openEndpoints starts all network and RPC endpoints.
  270. func (n *Node) openEndpoints() error {
  271. // start networking endpoints
  272. n.log.Info("Starting peer-to-peer node", "instance", n.server.Name)
  273. if err := n.server.Start(); err != nil {
  274. return convertFileLockError(err)
  275. }
  276. // Quorum
  277. if n.qserver != nil {
  278. if err := n.qserver.Start(); err != nil {
  279. return convertFileLockError(err)
  280. }
  281. }
  282. // End Quorum
  283. // start RPC endpoints
  284. err := n.startRPC()
  285. if err != nil {
  286. n.stopRPC()
  287. n.server.Stop()
  288. }
  289. return err
  290. }
  291. // containsLifecycle checks if 'lfs' contains 'l'.
  292. func containsLifecycle(lfs []Lifecycle, l Lifecycle) bool {
  293. for _, obj := range lfs {
  294. if obj == l {
  295. return true
  296. }
  297. }
  298. return false
  299. }
  300. // stopServices terminates running services, RPC and p2p networking.
  301. // It is the inverse of Start.
  302. func (n *Node) stopServices(running []Lifecycle) error {
  303. n.stopRPC()
  304. // Stop running lifecycles in reverse order.
  305. failure := &StopError{Services: make(map[reflect.Type]error)}
  306. // Quorum
  307. if err := n.PluginManager().Stop(); err != nil {
  308. failure.Services[reflect.TypeOf(n.PluginManager())] = err
  309. }
  310. // End Quorum
  311. for i := len(running) - 1; i >= 0; i-- {
  312. if err := running[i].Stop(); err != nil {
  313. failure.Services[reflect.TypeOf(running[i])] = err
  314. }
  315. }
  316. // Stop p2p networking.
  317. n.server.Stop()
  318. if n.qserver != nil {
  319. n.qserver.Stop()
  320. }
  321. if len(failure.Services) > 0 {
  322. return failure
  323. }
  324. return nil
  325. }
  326. func (n *Node) openDataDir() error {
  327. if n.config.DataDir == "" {
  328. return nil // ephemeral
  329. }
  330. instdir := filepath.Join(n.config.DataDir, n.config.name())
  331. if err := os.MkdirAll(instdir, 0700); err != nil {
  332. return err
  333. }
  334. // Lock the instance directory to prevent concurrent use by another instance as well as
  335. // accidental use of the instance directory as a database.
  336. release, _, err := fileutil.Flock(filepath.Join(instdir, "LOCK"))
  337. if err != nil {
  338. return convertFileLockError(err)
  339. }
  340. n.dirLock = release
  341. return nil
  342. }
  343. func (n *Node) closeDataDir() {
  344. // Release instance directory lock.
  345. if n.dirLock != nil {
  346. if err := n.dirLock.Release(); err != nil {
  347. n.log.Error("Can't release datadir lock", "err", err)
  348. }
  349. n.dirLock = nil
  350. }
  351. }
  352. // configureRPC is a helper method to configure all the various RPC endpoints during node
  353. // startup. It's not meant to be called at any time afterwards as it makes certain
  354. // assumptions about the state of the node.
  355. // Quorum
  356. // 1. Inject mutlitenancy flag into rpc server when appropriate
  357. func (n *Node) startRPC() error {
  358. if err := n.startInProc(); err != nil {
  359. return err
  360. }
  361. // Configure IPC.
  362. if n.ipc.endpoint != "" {
  363. if err := n.ipc.start(n.rpcAPIs); err != nil {
  364. return err
  365. }
  366. }
  367. tls, auth, err := n.GetSecuritySupports()
  368. if err != nil {
  369. return err
  370. }
  371. // Configure HTTP.
  372. if n.config.HTTPHost != "" {
  373. config := httpConfig{
  374. CorsAllowedOrigins: n.config.HTTPCors,
  375. Vhosts: n.config.HTTPVirtualHosts,
  376. Modules: n.config.HTTPModules,
  377. prefix: n.config.HTTPPathPrefix,
  378. }
  379. server := n.http
  380. if err := server.setListenAddr(n.config.HTTPHost, n.config.HTTPPort); err != nil {
  381. return err
  382. }
  383. if err := server.enableRPC(n.rpcAPIs, config, auth); err != nil {
  384. return err
  385. }
  386. }
  387. // Configure WebSocket.
  388. if n.config.WSHost != "" {
  389. server := n.wsServerForPort(n.config.WSPort)
  390. config := wsConfig{
  391. Modules: n.config.WSModules,
  392. Origins: n.config.WSOrigins,
  393. prefix: n.config.WSPathPrefix,
  394. }
  395. if err := server.setListenAddr(n.config.WSHost, n.config.WSPort); err != nil {
  396. return err
  397. }
  398. if err := server.enableWS(n.rpcAPIs, config, auth); err != nil {
  399. return err
  400. }
  401. }
  402. if err := n.http.start(tls); err != nil {
  403. return err
  404. }
  405. return n.ws.start(tls)
  406. }
  407. func (n *Node) wsServerForPort(port int) *httpServer {
  408. if n.config.HTTPHost == "" || n.http.port == port {
  409. return n.http
  410. }
  411. return n.ws
  412. }
  413. func (n *Node) stopRPC() {
  414. n.http.stop()
  415. n.ws.stop()
  416. n.ipc.stop()
  417. n.stopInProc()
  418. }
  419. // startInProc registers all RPC APIs on the inproc server.
  420. // Quorum
  421. // 1. Inject mutlitenancy flag into rpc server
  422. func (n *Node) startInProc() error {
  423. for _, api := range n.rpcAPIs {
  424. if err := n.inprocHandler.RegisterName(api.Namespace, api.Service); err != nil {
  425. return err
  426. }
  427. }
  428. return n.eventmux.Post(rpc.InProcServerReadyEvent{})
  429. }
  430. // stopInProc terminates the in-process RPC endpoint.
  431. func (n *Node) stopInProc() {
  432. n.inprocHandler.Stop()
  433. }
  434. // Wait blocks until the node is closed.
  435. func (n *Node) Wait() {
  436. <-n.stop
  437. }
  438. // RegisterLifecycle registers the given Lifecycle on the node.
  439. func (n *Node) RegisterLifecycle(lifecycle Lifecycle) {
  440. n.lock.Lock()
  441. defer n.lock.Unlock()
  442. if n.state != initializingState {
  443. panic("can't register lifecycle on running/stopped node")
  444. }
  445. if containsLifecycle(n.lifecycles, lifecycle) {
  446. panic(fmt.Sprintf("attempt to register lifecycle %T more than once", lifecycle))
  447. }
  448. n.lifecycles = append(n.lifecycles, lifecycle)
  449. }
  450. // RegisterProtocols adds backend's protocols to the node's p2p server.
  451. func (n *Node) RegisterProtocols(protocols []p2p.Protocol) {
  452. n.lock.Lock()
  453. defer n.lock.Unlock()
  454. if n.state != initializingState {
  455. panic("can't register protocols on running/stopped node")
  456. }
  457. n.server.Protocols = append(n.server.Protocols, protocols...)
  458. }
  459. func (n *Node) RegisterQProtocols(protocols []p2p.Protocol) {
  460. n.lock.Lock()
  461. defer n.lock.Unlock()
  462. if n.state != initializingState {
  463. panic("can't register protocols on running/stopped node")
  464. }
  465. n.qserver.Protocols = append(n.qserver.Protocols, protocols...)
  466. }
  467. // RegisterAPIs registers the APIs a service provides on the node.
  468. func (n *Node) RegisterAPIs(apis []rpc.API) {
  469. n.lock.Lock()
  470. defer n.lock.Unlock()
  471. if n.state != initializingState {
  472. panic("can't register APIs on running/stopped node")
  473. }
  474. n.rpcAPIs = append(n.rpcAPIs, apis...)
  475. }
  476. // RegisterHandler mounts a handler on the given path on the canonical HTTP server.
  477. //
  478. // The name of the handler is shown in a log message when the HTTP server starts
  479. // and should be a descriptive term for the service provided by the handler.
  480. func (n *Node) RegisterHandler(name, path string, handler http.Handler) {
  481. n.lock.Lock()
  482. defer n.lock.Unlock()
  483. if n.state != initializingState {
  484. panic("can't register HTTP handler on running/stopped node")
  485. }
  486. n.http.mux.Handle(path, handler)
  487. n.http.handlerNames[path] = name
  488. }
  489. // Attach creates an RPC client attached to an in-process API handler.
  490. func (n *Node) Attach() (*rpc.Client, error) {
  491. return rpc.DialInProc(n.inprocHandler), nil
  492. }
  493. // AttachWithPSI creates a PSI-specific RPC client attached to an in-process API handler.
  494. func (n *Node) AttachWithPSI(psi types.PrivateStateIdentifier) (*rpc.Client, error) {
  495. client, err := n.Attach()
  496. if err != nil {
  497. return nil, err
  498. }
  499. return client.WithPSI(psi), nil
  500. }
  501. // RPCHandler returns the in-process RPC request handler.
  502. func (n *Node) RPCHandler() (*rpc.Server, error) {
  503. n.lock.Lock()
  504. defer n.lock.Unlock()
  505. if n.state == closedState {
  506. return nil, ErrNodeStopped
  507. }
  508. return n.inprocHandler, nil
  509. }
  510. // Config returns the configuration of node.
  511. func (n *Node) Config() *Config {
  512. return n.config
  513. }
  514. // Server retrieves the currently running P2P network layer. This method is meant
  515. // only to inspect fields of the currently running server. Callers should not
  516. // start or stop the returned server.
  517. func (n *Node) Server() *p2p.Server {
  518. n.lock.Lock()
  519. defer n.lock.Unlock()
  520. return n.server
  521. }
  522. func (n *Node) QServer() *p2p.Server {
  523. n.lock.Lock()
  524. defer n.lock.Unlock()
  525. return n.qserver
  526. }
  527. // DataDir retrieves the current datadir used by the protocol stack.
  528. // Deprecated: No files should be stored in this directory, use InstanceDir instead.
  529. func (n *Node) DataDir() string {
  530. return n.config.DataDir
  531. }
  532. // InstanceDir retrieves the instance directory used by the protocol stack.
  533. func (n *Node) InstanceDir() string {
  534. return n.config.instanceDir()
  535. }
  536. // AccountManager retrieves the account manager used by the protocol stack.
  537. func (n *Node) AccountManager() *accounts.Manager {
  538. return n.accman
  539. }
  540. // IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
  541. func (n *Node) IPCEndpoint() string {
  542. return n.ipc.endpoint
  543. }
  544. // HTTPEndpoint returns the URL of the HTTP server. Note that this URL does not
  545. // contain the JSON-RPC path prefix set by HTTPPathPrefix.
  546. func (n *Node) HTTPEndpoint() string {
  547. return "http://" + n.http.listenAddr()
  548. }
  549. // WSEndpoint returns the current JSON-RPC over WebSocket endpoint.
  550. func (n *Node) WSEndpoint() string {
  551. if n.http.wsAllowed() {
  552. return "ws://" + n.http.listenAddr() + n.http.wsConfig.prefix
  553. }
  554. return "ws://" + n.ws.listenAddr() + n.ws.wsConfig.prefix
  555. }
  556. // EventMux retrieves the event multiplexer used by all the network services in
  557. // the current protocol stack.
  558. func (n *Node) EventMux() *event.TypeMux {
  559. return n.eventmux
  560. }
  561. // OpenDatabase opens an existing database with the given name (or creates one if no
  562. // previous can be found) from within the node's instance directory. If the node is
  563. // ephemeral, a memory database is returned.
  564. func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, readonly bool) (ethdb.Database, error) {
  565. n.lock.Lock()
  566. defer n.lock.Unlock()
  567. if n.state == closedState {
  568. return nil, ErrNodeStopped
  569. }
  570. var db ethdb.Database
  571. var err error
  572. if n.config.DataDir == "" {
  573. db = rawdb.NewMemoryDatabase()
  574. } else {
  575. db, err = rawdb.NewLevelDBDatabase(n.ResolvePath(name), cache, handles, namespace, readonly)
  576. }
  577. if err == nil {
  578. db = n.wrapDatabase(db)
  579. }
  580. return db, err
  581. }
  582. // OpenDatabaseWithFreezer opens an existing database with the given name (or
  583. // creates one if no previous can be found) from within the node's data directory,
  584. // also attaching a chain freezer to it that moves ancient chain data from the
  585. // database to immutable append-only files. If the node is an ephemeral one, a
  586. // memory database is returned.
  587. func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer, namespace string, readonly bool) (ethdb.Database, error) {
  588. n.lock.Lock()
  589. defer n.lock.Unlock()
  590. if n.state == closedState {
  591. return nil, ErrNodeStopped
  592. }
  593. var db ethdb.Database
  594. var err error
  595. if n.config.DataDir == "" {
  596. db = rawdb.NewMemoryDatabase()
  597. } else {
  598. root := n.ResolvePath(name)
  599. switch {
  600. case freezer == "":
  601. freezer = filepath.Join(root, "ancient")
  602. case !filepath.IsAbs(freezer):
  603. freezer = n.ResolvePath(freezer)
  604. }
  605. db, err = rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace, readonly)
  606. }
  607. if err == nil {
  608. db = n.wrapDatabase(db)
  609. }
  610. return db, err
  611. }
  612. // ResolvePath returns the absolute path of a resource in the instance directory.
  613. func (n *Node) ResolvePath(x string) string {
  614. return n.config.ResolvePath(x)
  615. }
  616. // closeTrackingDB wraps the Close method of a database. When the database is closed by the
  617. // service, the wrapper removes it from the node's database map. This ensures that Node
  618. // won't auto-close the database if it is closed by the service that opened it.
  619. type closeTrackingDB struct {
  620. ethdb.Database
  621. n *Node
  622. }
  623. func (db *closeTrackingDB) Close() error {
  624. db.n.lock.Lock()
  625. delete(db.n.databases, db)
  626. db.n.lock.Unlock()
  627. return db.Database.Close()
  628. }
  629. // wrapDatabase ensures the database will be auto-closed when Node is closed.
  630. func (n *Node) wrapDatabase(db ethdb.Database) ethdb.Database {
  631. wrapper := &closeTrackingDB{db, n}
  632. n.databases[wrapper] = struct{}{}
  633. return wrapper
  634. }
  635. // closeDatabases closes all open databases.
  636. func (n *Node) closeDatabases() (errors []error) {
  637. for db := range n.databases {
  638. delete(n.databases, db)
  639. if err := db.Database.Close(); err != nil {
  640. errors = append(errors, err)
  641. }
  642. }
  643. return errors
  644. }
  645. // Quorum
  646. func (n *Node) GetSecuritySupports() (tlsConfigSource security.TLSConfigurationSource, authManager security.AuthenticationManager, err error) {
  647. if n.pluginManager.IsEnabled(plugin.SecurityPluginInterfaceName) {
  648. sp := new(plugin.SecurityPluginTemplate)
  649. if err = n.pluginManager.GetPluginTemplate(plugin.SecurityPluginInterfaceName, sp); err != nil {
  650. return
  651. }
  652. if tlsConfigSource, err = sp.TLSConfigurationSource(); err != nil {
  653. return
  654. }
  655. if authManager, err = sp.AuthenticationManager(); err != nil {
  656. return
  657. }
  658. } else {
  659. log.Info("Security Plugin is not enabled")
  660. }
  661. return
  662. }
  663. // Quorum
  664. //
  665. // delegate call to node.Config
  666. func (n *Node) IsPermissionEnabled() bool {
  667. return n.config.IsPermissionEnabled()
  668. }
  669. // Quorum
  670. //
  671. // delegate call to node.Config
  672. func (n *Node) GetNodeKey() *ecdsa.PrivateKey {
  673. return n.config.NodeKey()
  674. }
  675. // Quorum
  676. //
  677. // This can be used to inspect plugins used in the current node
  678. func (n *Node) PluginManager() *plugin.PluginManager {
  679. return n.pluginManager
  680. }
  681. // Quorum
  682. //
  683. // This can be used to set the plugin manager in the node (replacing the default Empty one)
  684. func (n *Node) SetPluginManager(pm *plugin.PluginManager) {
  685. n.pluginManager = pm
  686. }
  687. // Quorum
  688. //
  689. // Lifecycle retrieves a currently lifecycle registered of a specific type.
  690. func (n *Node) Lifecycle(lifecycle interface{}) error {
  691. n.lock.Lock()
  692. defer n.lock.Unlock()
  693. // Short circuit if the node's not running
  694. if n.server == nil {
  695. return ErrNodeStopped
  696. }
  697. // Otherwise try to find the service to return
  698. element := reflect.ValueOf(lifecycle).Elem()
  699. for _, runningLifecycle := range n.lifecycles {
  700. lElem := reflect.TypeOf(runningLifecycle)
  701. if lElem == element.Type() {
  702. element.Set(reflect.ValueOf(runningLifecycle))
  703. return nil
  704. }
  705. }
  706. return ErrServiceUnknown
  707. }