Documentation ¶
Overview ¶
Package p2p implements the Ethereum p2p network protocols.
Index ¶
- Constants
- Variables
- func ExpectMsg(r MsgReader, code uint64, content interface{}) error
- func MsgPipe() (*MsgPipeRW, *MsgPipeRW)
- func Send(w MsgWriter, msgcode uint64, data interface{}) error
- func SendItems(w MsgWriter, msgcode uint64, elems ...interface{}) error
- type Cap
- type Config
- type DiscReason
- type Msg
- type MsgPipeRW
- type MsgReadWriter
- type MsgReader
- type MsgWriter
- type NodeDialer
- type NodeInfo
- type Peer
- func (p *Peer) Caps() []Cap
- func (p *Peer) Disconnect(reason DiscReason)
- func (p *Peer) Fullname() string
- func (p *Peer) ID() enode.ID
- func (p *Peer) Inbound() bool
- func (p *Peer) Info() *PeerInfo
- func (p *Peer) LocalAddr() net.Addr
- func (p *Peer) Log() log.Logger
- func (p *Peer) Name() string
- func (p *Peer) Node() *enode.Node
- func (p *Peer) RemoteAddr() net.Addr
- func (p *Peer) RunningCap(protocol string, versions []uint) bool
- func (p *Peer) String() string
- type PeerEvent
- type PeerEventType
- type PeerInfo
- type Protocol
- type Server
- func (srv *Server) AddPeer(node *enode.Node)
- func (srv *Server) AddTrustedPeer(node *enode.Node)
- func (srv *Server) LocalNode() *enode.LocalNode
- func (srv *Server) NodeInfo() *NodeInfo
- func (srv *Server) PeerCount() int
- func (srv *Server) Peers() []*Peer
- func (srv *Server) PeersInfo() []*PeerInfo
- func (srv *Server) RemovePeer(node *enode.Node)
- func (srv *Server) RemoveTrustedPeer(node *enode.Node)
- func (srv *Server) Self() *enode.Node
- func (srv *Server) SetupConn(fd net.Conn, flags connFlag, dialDest *enode.Node) error
- func (srv *Server) Start() (err error)
- func (srv *Server) Stop()
- func (srv *Server) SubscribeEvents(ch chan *PeerEvent) event.Subscription
Examples ¶
Constants ¶
const (
// HandleHistName is the prefix of the per-packet serving time histograms.
HandleHistName = "p2p/handle"
)
Variables ¶
var ErrPipeClosed = errors.New("p2p: read or write on closed message pipe")
ErrPipeClosed is returned from pipe operations after the pipe has been closed.
var (
ErrShuttingDown = errors.New("shutting down")
)
Functions ¶
func ExpectMsg ¶
ExpectMsg reads a message from r and verifies that its code and encoded RLP content match the provided values. If content is nil, the payload is discarded and not verified. 从r中读取一条消息判断是否与输入的code和content匹配
func MsgPipe ¶
MsgPipe creates a message pipe. Reads on one end are matched with writes on the other. The pipe is full-duplex, both ends implement MsgReadWriter. 创建一对MsgPipeRW对象,他们实现了MsgReadWriter接口
Example ¶
rw1, rw2 := MsgPipe() go func() { Send(rw1, 8, [][]byte{{0, 0}}) Send(rw1, 5, [][]byte{{1, 1}}) rw1.Close() }() for { msg, err := rw2.ReadMsg() if err != nil { break } var data [][]byte msg.Decode(&data) fmt.Printf("msg: %d, %x\n", msg.Code, data[0]) }
Output: msg: 8, 0000 msg: 5, 0101
func Send ¶
Send writes an RLP-encoded message with the given code. data should encode as an RLP list. 将消息msgcode和data通过w发送出去 首先将data转化成rlp编码,保存到io.Reader里后构造Msg对象 然后调用w.WriteMsg发送Msg对象
Types ¶
type Config ¶
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必须指定,而且必须指定一个大于零的数 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. // 可选值,默认为50 // 指正在进行握手阶段的连接个数,inbound和outbound分别进行计数 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. // 可选值,默认值3 // 代表本地主动拨号的节点上限个数所占MaxPeers的比例 // 默认是最多1/3的节点由本地主动拨号,剩下2/3由远程节点连接本地 DialRatio int `toml:",omitempty"` // NoDiscovery can be used to disable the peer discovery mechanism. // Disabling is useful for protocol debugging (manual topology). // 可选值,默认为false // 默认启用节点发现 NoDiscovery bool // DiscoveryV5 specifies whether the new topic-discovery based V5 discovery // protocol should be started or not. // 可选值,默认为false // 默认不启用v5版本的节点发现 DiscoveryV5 bool `toml:",omitempty"` // Name sets the node name of this server. // Use common.MakeName to create a name that follows existing conventions. // 可选值,本地节点的名称 // 通常使用common.MakeName方法来创建本地的名称 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中的节点不受到连接节点个数的限制 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. // 如果此字段不为nil,则本地指定的网段的ip的建立连接 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:"-"` // 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. // 可选值,默认是空字符串,代表不启动监听 // 如果设置端口为0,代表随机监听一个端口,服务器启动后会更新为真正监听的端口 ListenAddr string // If set to a non-nil value, the given NAT port mapper // is used to make the listening port available to the // Internet. // 不是nil,也不是nat.ExtIP的情况下 // 例如设置为nat.Any(),Server.Start会阻塞一会,探测节点的ip // nat.ExtIP是固定了本地的ip为指定的值,不需要再运行upnp或者pmp协议了 NAT nat.Interface `toml:",omitempty"` // If Dialer is set to a non-nil value, the given Dialer // is used to dial outbound peer connections. // 创建Server的时候可以指定自定义的拨号器 // 可选值,默认值nil,代表建立实际的tcp连接来拨号 // 如果是nil,将使用net.Dialer.DialContext进行拨号,也就是自定义的tcpDialer对象 Dialer NodeDialer `toml:"-"` // If NoDial is true, the server will not dial any peers. // 如果为true本地不会主动向外进行拨号 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"` // contains filtered or unexported fields }
Config holds Server options. 必须指定的字段 PrivateKey MaxPeers 必须指定大于零的整数 不指定ListenAddr将不会监听tcp连接
type DiscReason ¶
type DiscReason uint
断开连接的原因 Disconnect Reason
const ( DiscRequested DiscReason = iota DiscNetworkError DiscProtocolError DiscUselessPeer DiscTooManyPeers DiscAlreadyConnected DiscIncompatibleVersion DiscInvalidIdentity DiscQuitting DiscUnexpectedIdentity DiscSelf DiscReadTimeout DiscSubprotocolError = 0x10 )
func (DiscReason) String ¶
func (d DiscReason) String() string
type Msg ¶
type Msg struct { Code uint64 // 代表Payload中rlp编码的总长度 Size uint32 // Size of the raw payload Payload io.Reader // 消息接收到的时间 // 在Peer.readLoop函数中设置 ReceivedAt time.Time // contains filtered or unexported fields }
Msg defines the structure of a p2p message.
Note that a Msg can only be sent once since the Payload reader is consumed during sending. It is not possible to create a Msg and send it any number of times. If you want to reuse an encoded structure, encode the payload into a byte array and create a separate Msg with a bytes.Reader as Payload for each send. p2p网络中传递的消息对象 每个Msg对象只能发送一次,因为发送一次中后内部的Payload是io.Reader类型已经被读取完了
func (Msg) Decode ¶
Decode parses the RLP content of a message into the given value, which must be a pointer.
For the decoding rules, please see package rlp. 将Msg.Payload里保存的rlp编码解码成输入的类型 输入的变量必须是指针
type MsgPipeRW ¶
type MsgPipeRW struct {
// contains filtered or unexported fields
}
MsgPipeRW is an endpoint of a MsgReadWriter pipe. 实现了MsgReadWriter接口 内部保存了两个管道分别用来发送和接收数据
func (*MsgPipeRW) Close ¶
Close unblocks any pending ReadMsg and WriteMsg calls on both ends of the pipe. They will return ErrPipeClosed. Close also interrupts any reads from a message payload. Close函数的目的是关闭closing管道 使用额外变量closed来标记是否关闭过
type MsgReadWriter ¶
MsgReadWriter provides reading and writing of encoded messages. Implementations should ensure that ReadMsg and WriteMsg can be called simultaneously from multiple goroutines. 对消息可读可写 ReadMsg,WriteMsg
type MsgWriter ¶
type MsgWriter interface { // WriteMsg sends a message. It will block until the message's // Payload has been consumed by the other end. // // Note that messages can be sent only once because their // payload reader is drained. WriteMsg(Msg) error }
写入消息,WriteMsg
type NodeDialer ¶
NodeDialer is used to connect to nodes in the network, typically by using an underlying net.Dialer but also using net.Pipe in tests. 用来创建与另一个节点的连接 这个接口被tcpDialer和SimAdapter实现,tcpDialer是真正的网络连接,SimAdapter是使用内存管道 这个Dial方法传入的参数是Context和enode.Node 是对下面这个函数的封装,network一般直接指定为tcp,address由enode.Node解析出来 func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) {
type NodeInfo ¶
type NodeInfo struct { ID string `json:"id"` // Unique node identifier (also the encryption key) Name string `json:"name"` // Name of the node, including client type, version, OS, custom data Enode string `json:"enode"` // Enode URL for adding this peer from remote peers ENR string `json:"enr"` // Ethereum Node Record IP string `json:"ip"` // IP address of the node // 本地占用的两个端口 Ports struct { // UDP用于节点发现的端口 Discovery int `json:"discovery"` // UDP listening port for discovery protocol // TCP运行RLPx协议进行数据传输的端口 Listener int `json:"listener"` // TCP listening port for RLPx } `json:"ports"` ListenAddr string `json:"listenAddr"` Protocols map[string]interface{} `json:"protocols"` }
NodeInfo represents a short summary of the information known about the host. NodeInfo用来表示本地节点的各种信息 对应的是PeerInfo用来表示本地连接的其他节点的信息
type Peer ¶
type Peer struct {
// contains filtered or unexported fields
}
Peer represents a connected remote node. Peer代表一个本地已经连接的远程节点
func NewPeerPipe ¶
NewPeerPipe creates a peer for testing purposes. The message pipe given as the last parameter is closed when Disconnect is called on the peer.
func (*Peer) Disconnect ¶
func (p *Peer) Disconnect(reason DiscReason)
Disconnect terminates the peer connection with the given reason. It returns immediately and does not wait until the connection is closed.
func (*Peer) Fullname ¶
Fullname returns the node name that the remote node advertised. Fullname 就是在Server里定义的Name
func (*Peer) Inbound ¶
Inbound returns true if the peer is an inbound connection Inbound为true代表这个peer主动连接的本地 为false代表本地主动连接的这个peer
func (*Peer) Name ¶
Name returns an abbreviated form of the name Name如果是对Fullname的省略,小于20字节时Name和Fullname一致 Fullname超过20个字节后面使用省略号缩写
func (*Peer) RemoteAddr ¶
RemoteAddr returns the remote address of the network connection.
func (*Peer) RunningCap ¶
RunningCap returns true if the peer is actively connected using any of the enumerated versions of a specific protocol, meaning that at least one of the versions is supported by both this node and the peer p. 判断这个对等节点是否支持运行输入的协议
type PeerEvent ¶
type PeerEvent struct { Type PeerEventType `json:"type"` // 事件发生的节点,也就是接收到或发送消息的本地节点的id Peer enode.ID `json:"peer"` Error string `json:"error,omitempty"` Protocol string `json:"protocol,omitempty"` MsgCode *uint64 `json:"msg_code,omitempty"` MsgSize *uint32 `json:"msg_size,omitempty"` LocalAddress string `json:"local,omitempty"` RemoteAddress string `json:"remote,omitempty"` }
PeerEvent is an event emitted when peers are either added or dropped from a p2p.Server or when a message is sent or received on a peer connection PeerEvent总共有四种,分别是增加或者移除节点,以及接收或发送消息 PeerEventTypeAdd,PeerEventTypeDrop,PeerEventTypeMsgSend,PeerEventTypeMsgRecv
type PeerEventType ¶
type PeerEventType string
PeerEventType is the type of peer events emitted by a p2p.Server
const ( // PeerEventTypeAdd is the type of event emitted when a peer is added // to a p2p.Server PeerEventTypeAdd PeerEventType = "add" // PeerEventTypeDrop is the type of event emitted when a peer is // dropped from a p2p.Server PeerEventTypeDrop PeerEventType = "drop" // PeerEventTypeMsgSend is the type of event emitted when a // message is successfully sent to a peer PeerEventTypeMsgSend PeerEventType = "msgsend" // PeerEventTypeMsgRecv is the type of event emitted when a // message is received from a peer PeerEventTypeMsgRecv PeerEventType = "msgrecv" )
type PeerInfo ¶
type PeerInfo struct { ENR string `json:"enr,omitempty"` // Ethereum Node Record Enode string `json:"enode"` // Node URL ID string `json:"id"` // Unique node identifier Name string `json:"name"` // Name of the node, including client type, version, OS, custom data Caps []string `json:"caps"` // Protocols advertised by this peer Network struct { LocalAddress string `json:"localAddress"` // Local endpoint of the TCP data connection RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection Inbound bool `json:"inbound"` Trusted bool `json:"trusted"` Static bool `json:"static"` } `json:"network"` Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields }
PeerInfo represents a short summary of the information known about a connected peer. Sub-protocol independent fields are contained and initialized here, with protocol specifics delegated to all connected sub-protocols.
type Protocol ¶
type Protocol struct { // Name should contain the official protocol name, // often a three-letter word. // 官方的协议名称,一般是一个三个字母的单词 Name string // Version should contain the version number of the protocol. Version uint // Length should contain the number of message codes used // by the protocol. // 代表不同messsage code的个数,也就是消息的类型总数 // 由于message code从0开始,所以所有的message code都必须小于Length Length uint64 // Run is called in a new goroutine when the protocol has been // negotiated with a peer. It should read and write messages from // rw. The Payload for each message must be fully consumed. // // The peer connection is closed when Start returns. It should return // any protocol-level error (such as an I/O error) that is // encountered. // Run 在与一个节点握手成功后调用,在单独协程中执行. // 可以通过rw来接收和发送消息,所有接收的消息的Payload必须被全部读取 Run func(peer *Peer, rw MsgReadWriter) error // NodeInfo is an optional helper method to retrieve protocol specific metadata // about the host node. NodeInfo func() interface{} // PeerInfo is an optional helper method to retrieve protocol specific metadata // about a certain peer in the network. If an info retrieval function is set, // but returns nil, it is assumed that the protocol handshake is still running. PeerInfo func(id enode.ID) interface{} // DialCandidates, if non-nil, is a way to tell Server about protocol-specific nodes // that should be dialed. The server continuously reads nodes from the iterator and // attempts to create connections to them. // 用于为不同的协议指定不同的节点 DialCandidates enode.Iterator // Attributes contains protocol specific information for the node record. // 节点记录中增加的额外信息 Attributes []enr.Entry }
Protocol represents a P2P subprotocol implementation. 由外部定义的子协议对象
type Server ¶
type Server struct { // Config fields may not be modified while the server is running. Config DiscV5 *discover.UDPv5 // contains filtered or unexported fields }
Server manages all peer connections.
func (*Server) AddPeer ¶
AddPeer adds the given node to the static node set. When there is room in the peer set, the server will connect to the node. If the connection fails for any reason, the server will attempt to reconnect the peer. 添加静态节点
func (*Server) AddTrustedPeer ¶
AddTrustedPeer adds the given node to a reserved trusted list which allows the node to always connect, even if the slot are full.
func (*Server) NodeInfo ¶
NodeInfo gathers and returns a collection of metadata known about the host. 获取本地节点的相关信息
func (*Server) PeersInfo ¶
PeersInfo returns an array of metadata objects describing connected peers. 获取本地连接的所有节点的信息 返回的所有信息根据节点的ID从小到大排序
func (*Server) RemovePeer ¶
RemovePeer removes a node from the static node set. It also disconnects from the given node if it is currently connected as a peer.
This method blocks until all protocols have exited and the peer is removed. Do not use RemovePeer in protocol implementations, call Disconnect on the Peer instead. 从静态节点中删除指定的节点,然后断开与该节点的连接
func (*Server) RemoveTrustedPeer ¶
RemoveTrustedPeer removes the given node from the trusted peer set.
func (*Server) Self ¶
Self returns the local node's endpoint information. 获取Server对应的enode.Node对象 在Server调用Start前获取到v4版本 在Server调用Start后获取到enr记录
func (*Server) SetupConn ¶
SetupConn runs the handshakes and attempts to add the connection as a peer. It returns when the connection has been added as a peer or the handshakes have failed. Server必须已经调用了Start方法,在运行过程中 SetupConn在传入的net.Conn连接上执行握手过程,生成的所有net.Conn对象都会进入这里处理 如果握手成功将新增一个对等节点,否则返回错误 调用的时机有两个分别是
在listenLoop中本地监听到了来自远程发起的连接 本地对外部节点拨号成功获得了net.Conn对象,在dialTask.dial中调用
这是一个公开方法,外部如果建立了网络连接,也可以通过这个方法在该连接上执行握手过程,如果成功将添加一个Peer
func (*Server) Stop ¶
func (srv *Server) Stop()
Stop terminates the server and all active peer connections. It blocks until all active connections have been closed.
func (*Server) SubscribeEvents ¶
func (srv *Server) SubscribeEvents(ch chan *PeerEvent) event.Subscription
SubscribeEvents subscribes the given channel to peer events 订阅节点事件,每当有新节点添加或者删除的时候输入的管道会接收到通知
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
v4wire
Package v4wire implements the Discovery v4 Wire Protocol.
|
Package v4wire implements the Discovery v4 Wire Protocol. |
Package dnsdisc implements node discovery via DNS (EIP-1459).
|
Package dnsdisc implements node discovery via DNS (EIP-1459). |
Package enr implements Ethereum Node Records as defined in EIP-778.
|
Package enr implements Ethereum Node Records as defined in EIP-778. |
Package msgrate allows estimating the throughput of peers for more balanced syncs.
|
Package msgrate allows estimating the throughput of peers for more balanced syncs. |
Package nat provides access to common network port mapping protocols.
|
Package nat provides access to common network port mapping protocols. |
Package netutil contains extensions to the net package.
|
Package netutil contains extensions to the net package. |
Package rlpx implements the RLPx transport protocol.
|
Package rlpx implements the RLPx transport protocol. |
Package simulations simulates p2p networks.
|
Package simulations simulates p2p networks. |