// Node is a container on which services can be registered. type Node struct { eventmux event.TypeMux // Event multiplexer used between the services of a stack config Config accman *accounts.Manager

    1. ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
    2. instanceDirLock flock.Releaser // prevents concurrent use of instance directory
    3. serverConfig p2p.Config
    4. server *p2p.Server // Currently running P2P networking layer
    5. serviceFuncs []ServiceConstructor // Service constructors (in dependency order)
    6. services map[reflect.Type]Service // Currently running services
    7. rpcAPIs []rpc.API // List of APIs currently provided by the node
    8. inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
    9. ipcEndpoint string // IPC endpoint to listen at (empty = IPC disabled)
    10. ipcListener net.Listener // IPC RPC listener socket to serve API requests
    11. ipcHandler *rpc.Server // IPC RPC request handler to process the API requests
    12. httpEndpoint string // HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
    13. httpWhitelist []string // HTTP RPC modules to allow through this endpoint
    14. httpListener net.Listener // HTTP RPC listener socket to server API requests
    15. httpHandler *rpc.Server // HTTP RPC request handler to process the API requests
    16. wsEndpoint string // Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
    17. wsListener net.Listener // Websocket RPC listener socket to server API requests
    18. wsHandler *rpc.Server // Websocket RPC request handler to process the API requests
    19. stop chan struct{} // Channel to wait for termination notifications
    20. lock sync.RWMutex
    21. log log.Logger

    }

    创建p2p node // New creates a new P2P node, ready for protocol registration. func New(conf Config) (Node, error) { // Copy config and resolve the datadir so future changes to the current // working directory don’t affect the node. confCopy := *conf conf = &confCopy if conf.DataDir != “” { absdatadir, err := filepath.Abs(conf.DataDir) if err != nil { return nil, err } conf.DataDir = absdatadir } // 排除冲突 // Ensure that the instance name doesn’t cause weird conflicts with // other files in the data directory. if strings.ContainsAny(conf.Name, /\) { return nil, errors.New(Config.Name must not contain '/' or '\') } if conf.Name == datadirDefaultKeyStore { return nil, errors.New(Config.Name cannot be " + datadirDefaultKeyStore + ") } if strings.HasSuffix(conf.Name, “.ipc”) { return nil, errors.New(Config.Name cannot end in ".ipc") } // 创建AccountManager // Ensure that the AccountManager method works before the node has started. // We rely on this in cmd/geth. am, ephemeralKeystore, err := makeAccountManager(conf) if err != nil { return nil, err } if conf.Logger == nil { conf.Logger = log.New() } // Note: any interaction with Config that would create/touch files // in the data directory or instance directory is delayed until Start. return &Node{ accman: am, ephemeralKeystore: ephemeralKeystore, config: conf, serviceFuncs: []ServiceConstructor{}, ipcEndpoint: conf.IPCEndpoint(), httpEndpoint: conf.HTTPEndpoint(), wsEndpoint: conf.WSEndpoint(), eventmux: new(event.TypeMux), log: conf.Logger, }, nil }

    func makeAccountManager(conf Config) (accounts.Manager, string, error) { scryptN, scryptP, keydir, err := conf.AccountConfig() var ephemeral string if keydir == “” { // There is no datadir. keydir, err = ioutil.TempDir(“”, “go-ethereum-keystore”) ephemeral = keydir }

    1. if err != nil {
    2. return nil, "", err
    3. }
    4. if err := os.MkdirAll(keydir, 0700); err != nil {
    5. return nil, "", err
    6. }
    7. // Assemble the account manager and supported backends
    8. backends := []accounts.Backend{
    9. keystore.NewKeyStore(keydir, scryptN, scryptP),
    10. }
    11. if !conf.NoUSB {
    12. // Start a USB hub for Ledger hardware wallets
    13. if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil {
    14. log.Warn(fmt.Sprintf("Failed to start Ledger hub, disabling: %v", err))
    15. } else {
    16. backends = append(backends, ledgerhub)
    17. }
    18. // Start a USB hub for Trezor hardware wallets
    19. if trezorhub, err := usbwallet.NewTrezorHub(); err != nil {
    20. log.Warn(fmt.Sprintf("Failed to start Trezor hub, disabling: %v", err))
    21. } else {
    22. backends = append(backends, trezorhub)
    23. }
    24. }
    25. return accounts.NewManager(backends...), ephemeral, nil

    }

    创建live p2p节点,并运行他 // Start create a live P2P node and starts running it. func (n *Node) Start() error { n.lock.Lock() defer n.lock.Unlock()

    1. // Short circuit if the node's already running
    2. if n.server != nil {
    3. return ErrNodeRunning
    4. }
    5. if err := n.openDataDir(); err != nil {
    6. return err
    7. }
    8. // Initialize the p2p server. This creates the node key and
    9. // discovery databases.
    10. n.serverConfig = n.config.P2P
    11. n.serverConfig.PrivateKey = n.config.NodeKey()
    12. n.serverConfig.Name = n.config.NodeName()
    13. n.serverConfig.Logger = n.log
    14. if n.serverConfig.StaticNodes == nil {
    15. n.serverConfig.StaticNodes = n.config.StaticNodes()
    16. }
    17. if n.serverConfig.TrustedNodes == nil {
    18. n.serverConfig.TrustedNodes = n.config.TrustedNodes()
    19. }
    20. if n.serverConfig.NodeDatabase == "" {
    21. n.serverConfig.NodeDatabase = n.config.NodeDB()
    22. }
    23. running := &p2p.Server{Config: n.serverConfig}
    24. n.log.Info("Starting peer-to-peer node", "instance", n.serverConfig.Name)
    25. // Otherwise copy and specialize the P2P configuration
    26. services := make(map[reflect.Type]Service)
    27. for _, constructor := range n.serviceFuncs {
    28. // Create a new context for the particular service
    29. ctx := &ServiceContext{
    30. config: n.config,
    31. services: make(map[reflect.Type]Service),
    32. EventMux: n.eventmux,
    33. AccountManager: n.accman,
    34. }
    35. for kind, s := range services { // copy needed for threaded access
    36. ctx.services[kind] = s
    37. }
    38. // Construct and save the service
    39. service, err := constructor(ctx)
    40. if err != nil {
    41. return err
    42. }
    43. kind := reflect.TypeOf(service)
    44. if _, exists := services[kind]; exists {
    45. return &DuplicateServiceError{Kind: kind}
    46. }
    47. services[kind] = service
    48. }
    49. // Gather the protocols and start the freshly assembled P2P server
    50. for _, service := range services {
    51. running.Protocols = append(running.Protocols, service.Protocols()...)
    52. }
    53. if err := running.Start(); err != nil {
    54. return convertFileLockError(err)
    55. }
    56. // Start each of the services
    57. started := []reflect.Type{}
    58. for kind, service := range services {
    59. // Start the next service, stopping all previous upon failure
    60. if err := service.Start(running); err != nil {
    61. for _, kind := range started {
    62. services[kind].Stop()
    63. }
    64. running.Stop()
    65. return err
    66. }
    67. // Mark the service started for potential cleanup
    68. started = append(started, kind)
    69. }
    70. // Lastly start the configured RPC interfaces
    71. if err := n.startRPC(services); err != nil {
    72. for _, service := range services {
    73. service.Stop()
    74. }
    75. running.Stop()
    76. return err
    77. }
    78. // Finish initializing the startup
    79. n.services = services
    80. n.server = running
    81. n.stop = make(chan struct{})
    82. return nil

    }