go ethereum之p2p

简介

p2p是以太坊节点网络层的骨架,夹在底层 TCP/UDP 和应用协议(eth、snap、les)之间,管三件事:节点发现(谁在线)、连接管理(怎么连上、怎么断)、消息多路复用(连上了跑什么协议)

重要结构

主要有

  • Server
  • Peer:表示一个连接

Server结构定义为

go 复制代码
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
	discv4    *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
}

Config:p2p服务端配置

listener:监听器,接受连接

discv4,discv5,discmix:节点发现

dialsched:向外连接

peerOp:对接操作

localnode:结点的ENR

Peer结构定义为

go 复制代码
type Peer struct {
	rw      *conn
	running map[string]*protoRW
	log     log.Logger
	created mclock.AbsTime

	wg       sync.WaitGroup
	protoErr chan error
	closed   chan struct{}
	pingRecv chan struct{}
	disc     chan DiscReason

	// events receives message send / receive events if set
	events   *event.Feed
	testPipe *MsgPipeRW // for testing
}

启动

通过Start启动p2p,主要作以下事项

  • setupLocalNode:创建dev2p handshake和localnode
  • setupPortMapping:开启端口映射循环,根据NAT配置执行不同的协程
  • setupListening:开启监听协程listenLoop处理外部连接
  • setupDiscovery:开启节点发现,根据配置开启发现服务discv4,discv5
  • setupDialScheduler:开启拨号调度器dialScheduler,开启两个协程readNodesloop
  • srv.run():处理通道事件,如新连接等