github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:43</date> 10 //</624450114089390080> 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/enode" 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 //等待超时 35 bzzHandshakeTimeout = 3000 * time.Millisecond 36 ) 37 38 //bzzspec是通用群握手的规范 39 var BzzSpec = &protocols.Spec{ 40 Name: "bzz", 41 Version: 8, 42 MaxMsgSize: 10 * 1024 * 1024, 43 Messages: []interface{}{ 44 HandshakeMsg{}, 45 }, 46 } 47 48 //discovery spec是bzz discovery子协议的规范 49 var DiscoverySpec = &protocols.Spec{ 50 Name: "hive", 51 Version: 8, 52 MaxMsgSize: 10 * 1024 * 1024, 53 Messages: []interface{}{ 54 peersMsg{}, 55 subPeersMsg{}, 56 }, 57 } 58 59 //bzzconfig捕获配置单元使用的配置参数 60 type BzzConfig struct { 61 OverlayAddr []byte //覆盖网络的基址 62 UnderlayAddr []byte //节点的参考底图地址 63 HiveParams *HiveParams 64 NetworkID uint64 65 LightNode bool 66 } 67 68 //bzz是swarm协议包 69 type Bzz struct { 70 *Hive 71 NetworkID uint64 72 LightNode bool 73 localAddr *BzzAddr 74 mtx sync.Mutex 75 handshakes map[enode.ID]*HandshakeMsg 76 streamerSpec *protocols.Spec 77 streamerRun func(*BzzPeer) error 78 } 79 80 //Newzz是Swarm协议的构造者 81 //争论 82 //*BZZ配置 83 //*覆盖驱动程序 84 //*对等存储 85 func NewBzz(config *BzzConfig, kad *Kademlia, store state.Store, streamerSpec *protocols.Spec, streamerRun func(*BzzPeer) error) *Bzz { 86 return &Bzz{ 87 Hive: NewHive(config.HiveParams, kad, store), 88 NetworkID: config.NetworkID, 89 LightNode: config.LightNode, 90 localAddr: &BzzAddr{config.OverlayAddr, config.UnderlayAddr}, 91 handshakes: make(map[enode.ID]*HandshakeMsg), 92 streamerRun: streamerRun, 93 streamerSpec: streamerSpec, 94 } 95 } 96 97 //updateLocalAddr更新正在运行的节点的参考底图地址 98 func (b *Bzz) UpdateLocalAddr(byteaddr []byte) *BzzAddr { 99 b.localAddr = b.localAddr.Update(&BzzAddr{ 100 UAddr: byteaddr, 101 OAddr: b.localAddr.OAddr, 102 }) 103 return b.localAddr 104 } 105 106 //nodeinfo返回节点的覆盖地址 107 func (b *Bzz) NodeInfo() interface{} { 108 return b.localAddr.Address() 109 } 110 111 //协议返回Swarm提供的协议 112 //bzz实现node.service接口 113 //*握手/蜂窝 114 //*发现 115 func (b *Bzz) Protocols() []p2p.Protocol { 116 protocol := []p2p.Protocol{ 117 { 118 Name: BzzSpec.Name, 119 Version: BzzSpec.Version, 120 Length: BzzSpec.Length(), 121 Run: b.runBzz, 122 NodeInfo: b.NodeInfo, 123 }, 124 { 125 Name: DiscoverySpec.Name, 126 Version: DiscoverySpec.Version, 127 Length: DiscoverySpec.Length(), 128 Run: b.RunProtocol(DiscoverySpec, b.Hive.Run), 129 NodeInfo: b.Hive.NodeInfo, 130 PeerInfo: b.Hive.PeerInfo, 131 }, 132 } 133 if b.streamerSpec != nil && b.streamerRun != nil { 134 protocol = append(protocol, p2p.Protocol{ 135 Name: b.streamerSpec.Name, 136 Version: b.streamerSpec.Version, 137 Length: b.streamerSpec.Length(), 138 Run: b.RunProtocol(b.streamerSpec, b.streamerRun), 139 }) 140 } 141 return protocol 142 } 143 144 //API返回BZZ提供的API 145 //*蜂箱 146 //bzz实现node.service接口 147 func (b *Bzz) APIs() []rpc.API { 148 return []rpc.API{{ 149 Namespace: "hive", 150 Version: "3.0", 151 Service: b.Hive, 152 }} 153 } 154 155 //runprotocol是swarm子协议的包装器 156 //返回可分配给p2p.protocol run字段的p2p协议运行函数。 157 //争论: 158 //*P2P协议规范 159 //*以bzzpeer为参数运行函数 160 //此运行函数用于在协议会话期间阻塞 161 //返回时,会话终止,对等端断开连接。 162 //协议等待BZZ握手被协商 163 //bzzpeer上的覆盖地址是通过远程握手设置的。 164 func (b *Bzz) RunProtocol(spec *protocols.Spec, run func(*BzzPeer) error) func(*p2p.Peer, p2p.MsgReadWriter) error { 165 return func(p *p2p.Peer, rw p2p.MsgReadWriter) error { 166 //等待BZZ协议执行握手 167 handshake, _ := b.GetOrCreateHandshake(p.ID()) 168 defer b.removeHandshake(p.ID()) 169 select { 170 case <-handshake.done: 171 case <-time.After(bzzHandshakeTimeout): 172 return fmt.Errorf("%08x: %s protocol timeout waiting for handshake on %08x", b.BaseAddr()[:4], spec.Name, p.ID().Bytes()[:4]) 173 } 174 if handshake.err != nil { 175 return fmt.Errorf("%08x: %s protocol closed: %v", b.BaseAddr()[:4], spec.Name, handshake.err) 176 } 177 //握手成功,因此构造bzzpeer并运行协议 178 peer := &BzzPeer{ 179 Peer: protocols.NewPeer(p, rw, spec), 180 BzzAddr: handshake.peerAddr, 181 lastActive: time.Now(), 182 LightNode: handshake.LightNode, 183 } 184 185 log.Debug("peer created", "addr", handshake.peerAddr.String()) 186 187 return run(peer) 188 } 189 } 190 191 //performhandshake实现BZZ握手的协商 192 //在群子协议中共享 193 func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error { 194 ctx, cancel := context.WithTimeout(context.Background(), bzzHandshakeTimeout) 195 defer func() { 196 close(handshake.done) 197 cancel() 198 }() 199 rsh, err := p.Handshake(ctx, handshake, b.checkHandshake) 200 if err != nil { 201 handshake.err = err 202 return err 203 } 204 handshake.peerAddr = rsh.(*HandshakeMsg).Addr 205 handshake.LightNode = rsh.(*HandshakeMsg).LightNode 206 return nil 207 } 208 209 //run bzz是bzz基本协议的p2p协议运行函数 210 //与BZZ握手谈判 211 func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error { 212 handshake, _ := b.GetOrCreateHandshake(p.ID()) 213 if !<-handshake.init { 214 return fmt.Errorf("%08x: bzz already started on peer %08x", b.localAddr.Over()[:4], p.ID().Bytes()[:4]) 215 } 216 close(handshake.init) 217 defer b.removeHandshake(p.ID()) 218 peer := protocols.NewPeer(p, rw, BzzSpec) 219 err := b.performHandshake(peer, handshake) 220 if err != nil { 221 log.Warn(fmt.Sprintf("%08x: handshake failed with remote peer %08x: %v", b.localAddr.Over()[:4], p.ID().Bytes()[:4], err)) 222 223 return err 224 } 225 //如果我们再握手就失败了 226 msg, err := rw.ReadMsg() 227 if err != nil { 228 return err 229 } 230 msg.Discard() 231 return errors.New("received multiple handshakes") 232 } 233 234 //bzz peer是协议的bzz协议视图。peer(本身是p2p.peer的扩展) 235 //实现对等接口和所有接口对等实现:addr、overlaypeer 236 type BzzPeer struct { 237 *protocols.Peer //表示联机对等机的连接 238 *BzzAddr //远程地址->实现addr interface=protocols.peer 239 lastActive time.Time //当互斥锁释放时,时间会更新。 240 LightNode bool 241 } 242 243 func NewBzzPeer(p *protocols.Peer) *BzzPeer { 244 return &BzzPeer{Peer: p, BzzAddr: NewAddr(p.Node())} 245 } 246 247 //ID返回对等方的参考线节点标识符。 248 func (p *BzzPeer) ID() enode.ID { 249 //这是为了解决方法绑定:两个协议都嵌入了peer和bzzaddr。 250 //进入结构并提供id()。协议。对等版本更快,请确保 251 //得到使用。 252 return p.Peer.ID() 253 } 254 255 /* 256 257 258 *版本:协议的8字节整数版本 259 *networkid:8字节整数网络标识符 260 *地址:节点公布的地址,包括底层和覆盖连接。 261 **/ 262 263 type HandshakeMsg struct { 264 Version uint64 265 NetworkID uint64 266 Addr *BzzAddr 267 LightNode bool 268 269 //PeerAddr是对等握手中接收到的地址 270 peerAddr *BzzAddr 271 272 init chan bool 273 done chan struct{} 274 err error 275 } 276 277 //字符串漂亮地打印了握手 278 func (bh *HandshakeMsg) String() string { 279 return fmt.Sprintf("Handshake: Version: %v, NetworkID: %v, Addr: %v, LightNode: %v, peerAddr: %v", bh.Version, bh.NetworkID, bh.Addr, bh.LightNode, bh.peerAddr) 280 } 281 282 //执行启动握手并验证远程握手消息 283 func (b *Bzz) checkHandshake(hs interface{}) error { 284 rhs := hs.(*HandshakeMsg) 285 if rhs.NetworkID != b.NetworkID { 286 return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkID, b.NetworkID) 287 } 288 if rhs.Version != uint64(BzzSpec.Version) { 289 return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, BzzSpec.Version) 290 } 291 return nil 292 } 293 294 //removehandshake删除具有peerID的对等方的握手 295 //来自BZZ握手商店 296 func (b *Bzz) removeHandshake(peerID enode.ID) { 297 b.mtx.Lock() 298 defer b.mtx.Unlock() 299 delete(b.handshakes, peerID) 300 } 301 302 //gethandshake返回peerid远程对等机发送的bzz handshake 303 func (b *Bzz) GetOrCreateHandshake(peerID enode.ID) (*HandshakeMsg, bool) { 304 b.mtx.Lock() 305 defer b.mtx.Unlock() 306 handshake, found := b.handshakes[peerID] 307 if !found { 308 handshake = &HandshakeMsg{ 309 Version: uint64(BzzSpec.Version), 310 NetworkID: b.NetworkID, 311 Addr: b.localAddr, 312 LightNode: b.LightNode, 313 init: make(chan bool, 1), 314 done: make(chan struct{}), 315 } 316 //首次为远程对等机创建handhsake时 317 //它是用init初始化的 318 handshake.init <- true 319 b.handshakes[peerID] = handshake 320 } 321 322 return handshake, found 323 } 324 325 //bzzaddr实现peeraddr接口 326 type BzzAddr struct { 327 OAddr []byte 328 UAddr []byte 329 } 330 331 //地址实现覆盖中要使用的覆盖对等接口。 332 func (a *BzzAddr) Address() []byte { 333 return a.OAddr 334 } 335 336 //over返回覆盖地址。 337 func (a *BzzAddr) Over() []byte { 338 return a.OAddr 339 } 340 341 //在下返回参考底图地址。 342 func (a *BzzAddr) Under() []byte { 343 return a.UAddr 344 } 345 346 //ID返回参考底图中的节点标识符。 347 func (a *BzzAddr) ID() enode.ID { 348 n, err := enode.ParseV4(string(a.UAddr)) 349 if err != nil { 350 return enode.ID{} 351 } 352 return n.ID() 353 } 354 355 //更新更新更新对等记录的底层地址 356 func (a *BzzAddr) Update(na *BzzAddr) *BzzAddr { 357 return &BzzAddr{a.OAddr, na.UAddr} 358 } 359 360 //字符串漂亮地打印地址 361 func (a *BzzAddr) String() string { 362 return fmt.Sprintf("%x <%s>", a.OAddr, a.UAddr) 363 } 364 365 //randomaddr是从公钥生成地址的实用方法 366 func RandomAddr() *BzzAddr { 367 key, err := crypto.GenerateKey() 368 if err != nil { 369 panic("unable to generate key") 370 } 371 node := enode.NewV4(&key.PublicKey, net.IP{127, 0, 0, 1}, 30303, 30303) 372 return NewAddr(node) 373 } 374 375 //newaddr从节点记录构造bzzaddr。 376 func NewAddr(node *enode.Node) *BzzAddr { 377 return &BzzAddr{OAddr: node.ID().Bytes(), UAddr: []byte(node.String())} 378 } 379