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