github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/protocol.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:47</date> 10 //</624342672856846336> 11 12 13 package network 14 15 import ( 16 "context" 17 "errors" 18 "fmt" 19 "net" 20 "sync" 21 "time" 22 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/p2p" 25 "github.com/ethereum/go-ethereum/p2p/discover" 26 "github.com/ethereum/go-ethereum/p2p/protocols" 27 "github.com/ethereum/go-ethereum/rpc" 28 "github.com/ethereum/go-ethereum/swarm/log" 29 "github.com/ethereum/go-ethereum/swarm/state" 30 ) 31 32 const ( 33 DefaultNetworkID = 3 34 //protocolmaxmsgsize允许的最大消息大小 35 ProtocolMaxMsgSize = 10 * 1024 * 1024 36 //等待超时 37 bzzHandshakeTimeout = 3000 * time.Millisecond 38 ) 39 40 //bzzspec是通用群握手的规范 41 var BzzSpec = &protocols.Spec{ 42 Name: "bzz", 43 Version: 6, 44 MaxMsgSize: 10 * 1024 * 1024, 45 Messages: []interface{}{ 46 HandshakeMsg{}, 47 }, 48 } 49 50 //discovery spec是bzz discovery子协议的规范 51 var DiscoverySpec = &protocols.Spec{ 52 Name: "hive", 53 Version: 5, 54 MaxMsgSize: 10 * 1024 * 1024, 55 Messages: []interface{}{ 56 peersMsg{}, 57 subPeersMsg{}, 58 }, 59 } 60 61 //对等池所需的addr接口 62 type Addr interface { 63 OverlayPeer 64 Over() []byte 65 Under() []byte 66 String() string 67 Update(OverlayAddr) OverlayAddr 68 } 69 70 //对等接口表示实时对等连接 71 type Peer interface { 72 Addr //对等机的地址 73 Conn //实时连接(protocols.peer) 74 LastActive() time.Time //上次激活时间 75 } 76 77 //conn接口表示活动对等连接 78 type Conn interface { 79 ID() discover.NodeID //唯一标识对等池节点的键 80 Handshake(context.Context, interface{}, func(interface{}) error) (interface{}, error) //可以发送消息 81 Send(context.Context, interface{}) error // 82 Drop(error) // 83 Run(func(context.Context, interface{}) error) error // 84 Off() OverlayAddr 85 } 86 87 //bzzconfig捕获配置单元使用的配置参数 88 type BzzConfig struct { 89 OverlayAddr []byte //覆盖网络的基址 90 UnderlayAddr []byte //节点的参考底图地址 91 HiveParams *HiveParams 92 NetworkID uint64 93 LightNode bool 94 } 95 96 //bzz是swarm协议包 97 type Bzz struct { 98 *Hive 99 NetworkID uint64 100 LightNode bool 101 localAddr *BzzAddr 102 mtx sync.Mutex 103 handshakes map[discover.NodeID]*HandshakeMsg 104 streamerSpec *protocols.Spec 105 streamerRun func(*BzzPeer) error 106 } 107 108 //Newzz是Swarm协议的构造者 109 //争论 110 //*BZZ配置 111 //*覆盖驱动程序 112 //*对等存储 113 func NewBzz(config *BzzConfig, kad Overlay, store state.Store, streamerSpec *protocols.Spec, streamerRun func(*BzzPeer) error) *Bzz { 114 return &Bzz{ 115 Hive: NewHive(config.HiveParams, kad, store), 116 NetworkID: config.NetworkID, 117 LightNode: config.LightNode, 118 localAddr: &BzzAddr{config.OverlayAddr, config.UnderlayAddr}, 119 handshakes: make(map[discover.NodeID]*HandshakeMsg), 120 streamerRun: streamerRun, 121 streamerSpec: streamerSpec, 122 } 123 } 124 125 //updateLocalAddr更新正在运行的节点的参考底图地址 126 func (b *Bzz) UpdateLocalAddr(byteaddr []byte) *BzzAddr { 127 b.localAddr = b.localAddr.Update(&BzzAddr{ 128 UAddr: byteaddr, 129 OAddr: b.localAddr.OAddr, 130 }).(*BzzAddr) 131 return b.localAddr 132 } 133 134 //nodeinfo返回节点的覆盖地址 135 func (b *Bzz) NodeInfo() interface{} { 136 return b.localAddr.Address() 137 } 138 139 //协议返回Swarm提供的协议 140 //bzz实现node.service接口 141 //*握手/蜂窝 142 //*发现 143 func (b *Bzz) Protocols() []p2p.Protocol { 144 protocol := []p2p.Protocol{ 145 { 146 Name: BzzSpec.Name, 147 Version: BzzSpec.Version, 148 Length: BzzSpec.Length(), 149 Run: b.runBzz, 150 NodeInfo: b.NodeInfo, 151 }, 152 { 153 Name: DiscoverySpec.Name, 154 Version: DiscoverySpec.Version, 155 Length: DiscoverySpec.Length(), 156 Run: b.RunProtocol(DiscoverySpec, b.Hive.Run), 157 NodeInfo: b.Hive.NodeInfo, 158 PeerInfo: b.Hive.PeerInfo, 159 }, 160 } 161 if b.streamerSpec != nil && b.streamerRun != nil { 162 protocol = append(protocol, p2p.Protocol{ 163 Name: b.streamerSpec.Name, 164 Version: b.streamerSpec.Version, 165 Length: b.streamerSpec.Length(), 166 Run: b.RunProtocol(b.streamerSpec, b.streamerRun), 167 }) 168 } 169 return protocol 170 } 171 172 //API返回BZZ提供的API 173 //*蜂箱 174 //bzz实现node.service接口 175 func (b *Bzz) APIs() []rpc.API { 176 return []rpc.API{{ 177 Namespace: "hive", 178 Version: "3.0", 179 Service: b.Hive, 180 }} 181 } 182 183 //runprotocol是swarm子协议的包装器 184 //返回可分配给p2p.protocol run字段的p2p协议运行函数。 185 //争论: 186 //*P2P协议规范 187 //*以bzzpeer为参数运行函数 188 //此运行函数用于在协议会话期间阻塞 189 //返回时,会话终止,对等端断开连接。 190 //协议等待BZZ握手被协商 191 //bzzpeer上的覆盖地址是通过远程握手设置的。 192 func (b *Bzz) RunProtocol(spec *protocols.Spec, run func(*BzzPeer) error) func(*p2p.Peer, p2p.MsgReadWriter) error { 193 return func(p *p2p.Peer, rw p2p.MsgReadWriter) error { 194 //等待BZZ协议执行握手 195 handshake, _ := b.GetHandshake(p.ID()) 196 defer b.removeHandshake(p.ID()) 197 select { 198 case <-handshake.done: 199 case <-time.After(bzzHandshakeTimeout): 200 return fmt.Errorf("%08x: %s protocol timeout waiting for handshake on %08x", b.BaseAddr()[:4], spec.Name, p.ID().Bytes()[:4]) 201 } 202 if handshake.err != nil { 203 return fmt.Errorf("%08x: %s protocol closed: %v", b.BaseAddr()[:4], spec.Name, handshake.err) 204 } 205 //握手成功,因此构造bzzpeer并运行协议 206 peer := &BzzPeer{ 207 Peer: protocols.NewPeer(p, rw, spec), 208 localAddr: b.localAddr, 209 BzzAddr: handshake.peerAddr, 210 lastActive: time.Now(), 211 LightNode: handshake.LightNode, 212 } 213 214 log.Debug("peer created", "addr", handshake.peerAddr.String()) 215 216 return run(peer) 217 } 218 } 219 220 //performhandshake实现BZZ握手的协商 221 //在群子协议中共享 222 func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error { 223 ctx, cancel := context.WithTimeout(context.Background(), bzzHandshakeTimeout) 224 defer func() { 225 close(handshake.done) 226 cancel() 227 }() 228 rsh, err := p.Handshake(ctx, handshake, b.checkHandshake) 229 if err != nil { 230 handshake.err = err 231 return err 232 } 233 handshake.peerAddr = rsh.(*HandshakeMsg).Addr 234 handshake.LightNode = rsh.(*HandshakeMsg).LightNode 235 return nil 236 } 237 238 //run bzz是bzz基本协议的p2p协议运行函数 239 //与BZZ握手谈判 240 func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error { 241 handshake, _ := b.GetHandshake(p.ID()) 242 if !<-handshake.init { 243 return fmt.Errorf("%08x: bzz already started on peer %08x", b.localAddr.Over()[:4], ToOverlayAddr(p.ID().Bytes())[:4]) 244 } 245 close(handshake.init) 246 defer b.removeHandshake(p.ID()) 247 peer := protocols.NewPeer(p, rw, BzzSpec) 248 err := b.performHandshake(peer, handshake) 249 if err != nil { 250 log.Warn(fmt.Sprintf("%08x: handshake failed with remote peer %08x: %v", b.localAddr.Over()[:4], ToOverlayAddr(p.ID().Bytes())[:4], err)) 251 252 return err 253 } 254 //如果我们再握手就失败了 255 msg, err := rw.ReadMsg() 256 if err != nil { 257 return err 258 } 259 msg.Discard() 260 return errors.New("received multiple handshakes") 261 } 262 263 //bzz peer是协议的bzz协议视图。peer(本身是p2p.peer的扩展) 264 //实现对等接口和所有接口对等实现:addr、overlaypeer 265 type BzzPeer struct { 266 *protocols.Peer //表示联机对等机的连接 267 localAddr *BzzAddr //本地对等地址 268 *BzzAddr //远程地址->实现addr interface=protocols.peer 269 lastActive time.Time //当互斥锁释放时,时间会更新。 270 LightNode bool 271 } 272 273 func NewBzzTestPeer(p *protocols.Peer, addr *BzzAddr) *BzzPeer { 274 return &BzzPeer{ 275 Peer: p, 276 localAddr: addr, 277 BzzAddr: NewAddrFromNodeID(p.ID()), 278 } 279 } 280 281 //off返回脱机持久性的覆盖对等记录 282 func (p *BzzPeer) Off() OverlayAddr { 283 return p.BzzAddr 284 } 285 286 //LastActive返回上次激活对等机的时间 287 func (p *BzzPeer) LastActive() time.Time { 288 return p.lastActive 289 } 290 291 /* 292 握手 293 294 *版本:协议的8字节整数版本 295 *networkid:8字节整数网络标识符 296 *地址:节点公布的地址,包括底层和覆盖连接。 297 **/ 298 299 type HandshakeMsg struct { 300 Version uint64 301 NetworkID uint64 302 Addr *BzzAddr 303 LightNode bool 304 305 //PeerAddr是对等握手中接收到的地址 306 peerAddr *BzzAddr 307 308 init chan bool 309 done chan struct{} 310 err error 311 } 312 313 //字符串漂亮地打印了握手 314 func (bh *HandshakeMsg) String() string { 315 return fmt.Sprintf("Handshake: Version: %v, NetworkID: %v, Addr: %v, LightNode: %v, peerAddr: %v", bh.Version, bh.NetworkID, bh.Addr, bh.LightNode, bh.peerAddr) 316 } 317 318 //执行启动握手并验证远程握手消息 319 func (b *Bzz) checkHandshake(hs interface{}) error { 320 rhs := hs.(*HandshakeMsg) 321 if rhs.NetworkID != b.NetworkID { 322 return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkID, b.NetworkID) 323 } 324 if rhs.Version != uint64(BzzSpec.Version) { 325 return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, BzzSpec.Version) 326 } 327 return nil 328 } 329 330 //removehandshake删除具有peerID的对等方的握手 331 //来自BZZ握手商店 332 func (b *Bzz) removeHandshake(peerID discover.NodeID) { 333 b.mtx.Lock() 334 defer b.mtx.Unlock() 335 delete(b.handshakes, peerID) 336 } 337 338 //gethandshake返回peerid远程对等机发送的bzz handshake 339 func (b *Bzz) GetHandshake(peerID discover.NodeID) (*HandshakeMsg, bool) { 340 b.mtx.Lock() 341 defer b.mtx.Unlock() 342 handshake, found := b.handshakes[peerID] 343 if !found { 344 handshake = &HandshakeMsg{ 345 Version: uint64(BzzSpec.Version), 346 NetworkID: b.NetworkID, 347 Addr: b.localAddr, 348 LightNode: b.LightNode, 349 init: make(chan bool, 1), 350 done: make(chan struct{}), 351 } 352 //首次为远程对等机创建handhsake时 353 //它是用init初始化的 354 handshake.init <- true 355 b.handshakes[peerID] = handshake 356 } 357 358 return handshake, found 359 } 360 361 //bzzaddr实现peeraddr接口 362 type BzzAddr struct { 363 OAddr []byte 364 UAddr []byte 365 } 366 367 //地址实现覆盖中要使用的覆盖对等接口 368 func (a *BzzAddr) Address() []byte { 369 return a.OAddr 370 } 371 372 //over返回覆盖地址 373 func (a *BzzAddr) Over() []byte { 374 return a.OAddr 375 } 376 377 //在下面返回参考底图地址 378 func (a *BzzAddr) Under() []byte { 379 return a.UAddr 380 } 381 382 //id返回参考底图enode地址中的nodeid 383 func (a *BzzAddr) ID() discover.NodeID { 384 return discover.MustParseNode(string(a.UAddr)).ID 385 } 386 387 //更新更新更新对等记录的底层地址 388 func (a *BzzAddr) Update(na OverlayAddr) OverlayAddr { 389 return &BzzAddr{a.OAddr, na.(Addr).Under()} 390 } 391 392 //字符串漂亮地打印地址 393 func (a *BzzAddr) String() string { 394 return fmt.Sprintf("%x <%s>", a.OAddr, a.UAddr) 395 } 396 397 //randomaddr是从公钥生成地址的实用方法 398 func RandomAddr() *BzzAddr { 399 key, err := crypto.GenerateKey() 400 if err != nil { 401 panic("unable to generate key") 402 } 403 pubkey := crypto.FromECDSAPub(&key.PublicKey) 404 var id discover.NodeID 405 copy(id[:], pubkey[1:]) 406 return NewAddrFromNodeID(id) 407 } 408 409 //newnodeidfromaddr将底层地址转换为adapters.nodeid 410 func NewNodeIDFromAddr(addr Addr) discover.NodeID { 411 log.Info(fmt.Sprintf("uaddr=%s", string(addr.Under()))) 412 node := discover.MustParseNode(string(addr.Under())) 413 return node.ID 414 } 415 416 //newAddrFromNodeID从discover.nodeID构造BzzAddr 417 //覆盖地址是作为nodeid的散列派生的。 418 func NewAddrFromNodeID(id discover.NodeID) *BzzAddr { 419 return &BzzAddr{ 420 OAddr: ToOverlayAddr(id.Bytes()), 421 UAddr: []byte(discover.NewNode(id, net.IP{127, 0, 0, 1}, 30303, 30303).String()), 422 } 423 } 424 425 //newaddrFromNodeAndPort从discover.nodeid和端口uint16构造bzzaddr 426 //覆盖地址是作为nodeid的散列派生的。 427 func NewAddrFromNodeIDAndPort(id discover.NodeID, host net.IP, port uint16) *BzzAddr { 428 return &BzzAddr{ 429 OAddr: ToOverlayAddr(id.Bytes()), 430 UAddr: []byte(discover.NewNode(id, host, port, port).String()), 431 } 432 } 433 434 //ToOverlayAddr从字节片创建覆盖地址 435 func ToOverlayAddr(id []byte) []byte { 436 return crypto.Keccak256(id) 437 } 438