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