Server Config and Creation

We can see the server creation process from the startTestServer in test file:
  1. It constructs config of the server.
  1. initialize a Server instance
  1. call server.Start to run the server.
/// ---p2p/server_test.go--- func startTestServer(t *testing.T, remoteKey *ecdsa.PublicKey, pf func(*Peer)) *Server { config := Config{ Name: "test", MaxPeers: 10, ListenAddr: "127.0.0.1:0", NoDiscovery: true, PrivateKey: newkey(), Logger: testlog.Logger(t, log.LvlTrace), } server := &Server{ Config: config, newPeerHook: pf, newTransport: func(fd net.Conn, dialDest *ecdsa.PublicKey) transport { return newTestTransport(remoteKey, fd, dialDest) }, } if err := server.Start(); err != nil { t.Fatalf("Could not start server: %v", err) } return server }
 
There are a lot configurations in the Server, some important configurations:
  1. PrivateKey
      • Each Ethereum node is identified by a unique NodeID, which is derived from the node's public key. The PrivateKey is used to generate this public key.
      • The PrivateKey is used in the RLPx handshake process, which establishes an encrypted and authenticated connection between nodes. It ensures that the communication between nodes is secure and that the identity of each node is verified.
  1. Protocols
      • Specify the set of protocols that the server supports. Each protocol defines a set of message types and behaviors for handling those messages, enabling different types of communication and functionality between peers in the Ethereum network. Examples of protocols include the eth protocol for blockchain data (blocks and transactions).
/// ---p2p/server.go--- // Config holds Server options. type Config struct { // This field must be set to a valid secp256k1 private key. PrivateKey *ecdsa.PrivateKey `toml:"-"` // MaxPeers is the maximum number of peers that can be // connected. It must be greater than zero. MaxPeers int // MaxPendingPeers is the maximum number of peers that can be pending in the // handshake phase, counted separately for inbound and outbound connections. // Zero defaults to preset values. MaxPendingPeers int `toml:",omitempty"` // DialRatio controls the ratio of inbound to dialed connections. // Example: a DialRatio of 2 allows 1/2 of connections to be dialed. // Setting DialRatio to zero defaults it to 3. DialRatio int `toml:",omitempty"` // NoDiscovery can be used to disable the peer discovery mechanism. // Disabling is useful for protocol debugging (manual topology). NoDiscovery bool // DiscoveryV4 specifies whether V4 discovery should be started. DiscoveryV4 bool `toml:",omitempty"` // DiscoveryV5 specifies whether the new topic-discovery based V5 discovery // protocol should be started or not. DiscoveryV5 bool `toml:",omitempty"` // Name sets the node name of this server. Name string `toml:"-"` // BootstrapNodes are used to establish connectivity // with the rest of the network. BootstrapNodes []*enode.Node // BootstrapNodesV5 are used to establish connectivity // with the rest of the network using the V5 discovery // protocol. BootstrapNodesV5 []*enode.Node `toml:",omitempty"` // Static nodes are used as pre-configured connections which are always // maintained and re-connected on disconnects. StaticNodes []*enode.Node // Trusted nodes are used as pre-configured connections which are always // allowed to connect, even above the peer limit. TrustedNodes []*enode.Node // Connectivity can be restricted to certain IP networks. // If this option is set to a non-nil value, only hosts which match one of the // IP networks contained in the list are considered. NetRestrict *netutil.Netlist `toml:",omitempty"` // NodeDatabase is the path to the database containing the previously seen // live nodes in the network. NodeDatabase string `toml:",omitempty"` // Protocols should contain the protocols supported // by the server. Matching protocols are launched for // each peer. Protocols []Protocol `toml:"-" json:"-"` // If ListenAddr is set to a non-nil address, the server // will listen for incoming connections. // // If the port is zero, the operating system will pick a port. The // ListenAddr field will be updated with the actual address when // the server is started. ListenAddr string // If DiscAddr is set to a non-nil value, the server will use ListenAddr // for TCP and DiscAddr for the UDP discovery protocol. DiscAddr string // If set to a non-nil value, the given NAT port mapper // is used to make the listening port available to the // Internet. NAT nat.Interface `toml:",omitempty"` // If Dialer is set to a non-nil value, the given Dialer // is used to dial outbound peer connections. Dialer NodeDialer `toml:"-"` // If NoDial is true, the server will not dial any peers. NoDial bool `toml:",omitempty"` // If EnableMsgEvents is set then the server will emit PeerEvents // whenever a message is sent to or received from a peer EnableMsgEvents bool // Logger is a custom logger to use with the p2p.Server. Logger log.Logger `toml:",omitempty"` clock mclock.Clock } // Server manages all peer connections. type Server struct { // Config fields may not be modified while the server is running. Config // Hooks for testing. These are useful because we can inhibit // the whole protocol stack. newTransport func(net.Conn, *ecdsa.PublicKey) transport newPeerHook func(*Peer) listenFunc func(network, addr string) (net.Listener, error) lock sync.Mutex // protects running running bool listener net.Listener ourHandshake *protoHandshake loopWG sync.WaitGroup // loop, listenLoop peerFeed event.Feed log log.Logger nodedb *enode.DB localnode *enode.LocalNode ntab *discover.UDPv4 DiscV5 *discover.UDPv5 discmix *enode.FairMix dialsched *dialScheduler // This is read by the NAT port mapping loop. portMappingRegister chan *portMapping // Channels into the run loop. quit chan struct{} addtrusted chan *enode.Node removetrusted chan *enode.Node peerOp chan peerOpFunc peerOpDone chan struct{} delpeer chan peerDrop checkpointPostHandshake chan *conn checkpointAddPeer chan *conn // State of run loop and listenLoop. inboundHistory expHeap }