github.com/gobitfly/go-ethereum@v1.8.12/swarm/network/protocol.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package network 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "net" 24 "sync" 25 "time" 26 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/p2p" 29 "github.com/ethereum/go-ethereum/p2p/discover" 30 "github.com/ethereum/go-ethereum/p2p/protocols" 31 "github.com/ethereum/go-ethereum/rpc" 32 "github.com/ethereum/go-ethereum/swarm/log" 33 "github.com/ethereum/go-ethereum/swarm/state" 34 ) 35 36 const ( 37 DefaultNetworkID = 3 38 // ProtocolMaxMsgSize maximum allowed message size 39 ProtocolMaxMsgSize = 10 * 1024 * 1024 40 // timeout for waiting 41 bzzHandshakeTimeout = 3000 * time.Millisecond 42 ) 43 44 // BzzSpec is the spec of the generic swarm handshake 45 var BzzSpec = &protocols.Spec{ 46 Name: "bzz", 47 Version: 4, 48 MaxMsgSize: 10 * 1024 * 1024, 49 Messages: []interface{}{ 50 HandshakeMsg{}, 51 }, 52 } 53 54 // DiscoverySpec is the spec for the bzz discovery subprotocols 55 var DiscoverySpec = &protocols.Spec{ 56 Name: "hive", 57 Version: 4, 58 MaxMsgSize: 10 * 1024 * 1024, 59 Messages: []interface{}{ 60 peersMsg{}, 61 subPeersMsg{}, 62 }, 63 } 64 65 // Addr interface that peerPool needs 66 type Addr interface { 67 OverlayPeer 68 Over() []byte 69 Under() []byte 70 String() string 71 Update(OverlayAddr) OverlayAddr 72 } 73 74 // Peer interface represents an live peer connection 75 type Peer interface { 76 Addr // the address of a peer 77 Conn // the live connection (protocols.Peer) 78 LastActive() time.Time // last time active 79 } 80 81 // Conn interface represents an live peer connection 82 type Conn interface { 83 ID() discover.NodeID // the key that uniquely identifies the Node for the peerPool 84 Handshake(context.Context, interface{}, func(interface{}) error) (interface{}, error) // can send messages 85 Send(interface{}) error // can send messages 86 Drop(error) // disconnect this peer 87 Run(func(interface{}) error) error // the run function to run a protocol 88 Off() OverlayAddr 89 } 90 91 // BzzConfig captures the config params used by the hive 92 type BzzConfig struct { 93 OverlayAddr []byte // base address of the overlay network 94 UnderlayAddr []byte // node's underlay address 95 HiveParams *HiveParams 96 NetworkID uint64 97 } 98 99 // Bzz is the swarm protocol bundle 100 type Bzz struct { 101 *Hive 102 NetworkID uint64 103 localAddr *BzzAddr 104 mtx sync.Mutex 105 handshakes map[discover.NodeID]*HandshakeMsg 106 streamerSpec *protocols.Spec 107 streamerRun func(*BzzPeer) error 108 } 109 110 // NewBzz is the swarm protocol constructor 111 // arguments 112 // * bzz config 113 // * overlay driver 114 // * peer store 115 func NewBzz(config *BzzConfig, kad Overlay, store state.Store, streamerSpec *protocols.Spec, streamerRun func(*BzzPeer) error) *Bzz { 116 return &Bzz{ 117 Hive: NewHive(config.HiveParams, kad, store), 118 NetworkID: config.NetworkID, 119 localAddr: &BzzAddr{config.OverlayAddr, config.UnderlayAddr}, 120 handshakes: make(map[discover.NodeID]*HandshakeMsg), 121 streamerRun: streamerRun, 122 streamerSpec: streamerSpec, 123 } 124 } 125 126 // UpdateLocalAddr updates underlayaddress of the running node 127 func (b *Bzz) UpdateLocalAddr(byteaddr []byte) *BzzAddr { 128 b.localAddr = b.localAddr.Update(&BzzAddr{ 129 UAddr: byteaddr, 130 OAddr: b.localAddr.OAddr, 131 }).(*BzzAddr) 132 return b.localAddr 133 } 134 135 // NodeInfo returns the node's overlay address 136 func (b *Bzz) NodeInfo() interface{} { 137 return b.localAddr.Address() 138 } 139 140 // Protocols return the protocols swarm offers 141 // Bzz implements the node.Service interface 142 // * handshake/hive 143 // * discovery 144 func (b *Bzz) Protocols() []p2p.Protocol { 145 protocol := []p2p.Protocol{ 146 { 147 Name: BzzSpec.Name, 148 Version: BzzSpec.Version, 149 Length: BzzSpec.Length(), 150 Run: b.runBzz, 151 NodeInfo: b.NodeInfo, 152 }, 153 { 154 Name: DiscoverySpec.Name, 155 Version: DiscoverySpec.Version, 156 Length: DiscoverySpec.Length(), 157 Run: b.RunProtocol(DiscoverySpec, b.Hive.Run), 158 NodeInfo: b.Hive.NodeInfo, 159 PeerInfo: b.Hive.PeerInfo, 160 }, 161 } 162 if b.streamerSpec != nil && b.streamerRun != nil { 163 protocol = append(protocol, p2p.Protocol{ 164 Name: b.streamerSpec.Name, 165 Version: b.streamerSpec.Version, 166 Length: b.streamerSpec.Length(), 167 Run: b.RunProtocol(b.streamerSpec, b.streamerRun), 168 }) 169 } 170 return protocol 171 } 172 173 // APIs returns the APIs offered by bzz 174 // * hive 175 // Bzz implements the node.Service interface 176 func (b *Bzz) APIs() []rpc.API { 177 return []rpc.API{{ 178 Namespace: "hive", 179 Version: "3.0", 180 Service: b.Hive, 181 }} 182 } 183 184 // RunProtocol is a wrapper for swarm subprotocols 185 // returns a p2p protocol run function that can be assigned to p2p.Protocol#Run field 186 // arguments: 187 // * p2p protocol spec 188 // * run function taking BzzPeer as argument 189 // this run function is meant to block for the duration of the protocol session 190 // on return the session is terminated and the peer is disconnected 191 // the protocol waits for the bzz handshake is negotiated 192 // the overlay address on the BzzPeer is set from the remote handshake 193 func (b *Bzz) RunProtocol(spec *protocols.Spec, run func(*BzzPeer) error) func(*p2p.Peer, p2p.MsgReadWriter) error { 194 return func(p *p2p.Peer, rw p2p.MsgReadWriter) error { 195 // wait for the bzz protocol to perform the handshake 196 handshake, _ := b.GetHandshake(p.ID()) 197 defer b.removeHandshake(p.ID()) 198 select { 199 case <-handshake.done: 200 case <-time.After(bzzHandshakeTimeout): 201 return fmt.Errorf("%08x: %s protocol timeout waiting for handshake on %08x", b.BaseAddr()[:4], spec.Name, p.ID().Bytes()[:4]) 202 } 203 if handshake.err != nil { 204 return fmt.Errorf("%08x: %s protocol closed: %v", b.BaseAddr()[:4], spec.Name, handshake.err) 205 } 206 // the handshake has succeeded so construct the BzzPeer and run the protocol 207 peer := &BzzPeer{ 208 Peer: protocols.NewPeer(p, rw, spec), 209 localAddr: b.localAddr, 210 BzzAddr: handshake.peerAddr, 211 lastActive: time.Now(), 212 } 213 return run(peer) 214 } 215 } 216 217 // performHandshake implements the negotiation of the bzz handshake 218 // shared among swarm subprotocols 219 func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error { 220 ctx, cancel := context.WithTimeout(context.Background(), bzzHandshakeTimeout) 221 defer func() { 222 close(handshake.done) 223 cancel() 224 }() 225 rsh, err := p.Handshake(ctx, handshake, b.checkHandshake) 226 if err != nil { 227 handshake.err = err 228 return err 229 } 230 handshake.peerAddr = rsh.(*HandshakeMsg).Addr 231 return nil 232 } 233 234 // runBzz is the p2p protocol run function for the bzz base protocol 235 // that negotiates the bzz handshake 236 func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error { 237 handshake, _ := b.GetHandshake(p.ID()) 238 if !<-handshake.init { 239 return fmt.Errorf("%08x: bzz already started on peer %08x", b.localAddr.Over()[:4], ToOverlayAddr(p.ID().Bytes())[:4]) 240 } 241 close(handshake.init) 242 defer b.removeHandshake(p.ID()) 243 peer := protocols.NewPeer(p, rw, BzzSpec) 244 err := b.performHandshake(peer, handshake) 245 if err != nil { 246 log.Warn(fmt.Sprintf("%08x: handshake failed with remote peer %08x: %v", b.localAddr.Over()[:4], ToOverlayAddr(p.ID().Bytes())[:4], err)) 247 248 return err 249 } 250 // fail if we get another handshake 251 msg, err := rw.ReadMsg() 252 if err != nil { 253 return err 254 } 255 msg.Discard() 256 return errors.New("received multiple handshakes") 257 } 258 259 // BzzPeer is the bzz protocol view of a protocols.Peer (itself an extension of p2p.Peer) 260 // implements the Peer interface and all interfaces Peer implements: Addr, OverlayPeer 261 type BzzPeer struct { 262 *protocols.Peer // represents the connection for online peers 263 localAddr *BzzAddr // local Peers address 264 *BzzAddr // remote address -> implements Addr interface = protocols.Peer 265 lastActive time.Time // time is updated whenever mutexes are releasing 266 } 267 268 func NewBzzTestPeer(p *protocols.Peer, addr *BzzAddr) *BzzPeer { 269 return &BzzPeer{ 270 Peer: p, 271 localAddr: addr, 272 BzzAddr: NewAddrFromNodeID(p.ID()), 273 } 274 } 275 276 // Off returns the overlay peer record for offline persistence 277 func (p *BzzPeer) Off() OverlayAddr { 278 return p.BzzAddr 279 } 280 281 // LastActive returns the time the peer was last active 282 func (p *BzzPeer) LastActive() time.Time { 283 return p.lastActive 284 } 285 286 /* 287 Handshake 288 289 * Version: 8 byte integer version of the protocol 290 * NetworkID: 8 byte integer network identifier 291 * Addr: the address advertised by the node including underlay and overlay connecctions 292 */ 293 type HandshakeMsg struct { 294 Version uint64 295 NetworkID uint64 296 Addr *BzzAddr 297 298 // peerAddr is the address received in the peer handshake 299 peerAddr *BzzAddr 300 301 init chan bool 302 done chan struct{} 303 err error 304 } 305 306 // String pretty prints the handshake 307 func (bh *HandshakeMsg) String() string { 308 return fmt.Sprintf("Handshake: Version: %v, NetworkID: %v, Addr: %v", bh.Version, bh.NetworkID, bh.Addr) 309 } 310 311 // Perform initiates the handshake and validates the remote handshake message 312 func (b *Bzz) checkHandshake(hs interface{}) error { 313 rhs := hs.(*HandshakeMsg) 314 if rhs.NetworkID != b.NetworkID { 315 return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkID, b.NetworkID) 316 } 317 if rhs.Version != uint64(BzzSpec.Version) { 318 return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, BzzSpec.Version) 319 } 320 return nil 321 } 322 323 // removeHandshake removes handshake for peer with peerID 324 // from the bzz handshake store 325 func (b *Bzz) removeHandshake(peerID discover.NodeID) { 326 b.mtx.Lock() 327 defer b.mtx.Unlock() 328 delete(b.handshakes, peerID) 329 } 330 331 // GetHandshake returns the bzz handhake that the remote peer with peerID sent 332 func (b *Bzz) GetHandshake(peerID discover.NodeID) (*HandshakeMsg, bool) { 333 b.mtx.Lock() 334 defer b.mtx.Unlock() 335 handshake, found := b.handshakes[peerID] 336 if !found { 337 handshake = &HandshakeMsg{ 338 Version: uint64(BzzSpec.Version), 339 NetworkID: b.NetworkID, 340 Addr: b.localAddr, 341 init: make(chan bool, 1), 342 done: make(chan struct{}), 343 } 344 // when handhsake is first created for a remote peer 345 // it is initialised with the init 346 handshake.init <- true 347 b.handshakes[peerID] = handshake 348 } 349 350 return handshake, found 351 } 352 353 // BzzAddr implements the PeerAddr interface 354 type BzzAddr struct { 355 OAddr []byte 356 UAddr []byte 357 } 358 359 // Address implements OverlayPeer interface to be used in Overlay 360 func (a *BzzAddr) Address() []byte { 361 return a.OAddr 362 } 363 364 // Over returns the overlay address 365 func (a *BzzAddr) Over() []byte { 366 return a.OAddr 367 } 368 369 // Under returns the underlay address 370 func (a *BzzAddr) Under() []byte { 371 return a.UAddr 372 } 373 374 // ID returns the nodeID from the underlay enode address 375 func (a *BzzAddr) ID() discover.NodeID { 376 return discover.MustParseNode(string(a.UAddr)).ID 377 } 378 379 // Update updates the underlay address of a peer record 380 func (a *BzzAddr) Update(na OverlayAddr) OverlayAddr { 381 return &BzzAddr{a.OAddr, na.(Addr).Under()} 382 } 383 384 // String pretty prints the address 385 func (a *BzzAddr) String() string { 386 return fmt.Sprintf("%x <%s>", a.OAddr, a.UAddr) 387 } 388 389 // RandomAddr is a utility method generating an address from a public key 390 func RandomAddr() *BzzAddr { 391 key, err := crypto.GenerateKey() 392 if err != nil { 393 panic("unable to generate key") 394 } 395 pubkey := crypto.FromECDSAPub(&key.PublicKey) 396 var id discover.NodeID 397 copy(id[:], pubkey[1:]) 398 return NewAddrFromNodeID(id) 399 } 400 401 // NewNodeIDFromAddr transforms the underlay address to an adapters.NodeID 402 func NewNodeIDFromAddr(addr Addr) discover.NodeID { 403 log.Info(fmt.Sprintf("uaddr=%s", string(addr.Under()))) 404 node := discover.MustParseNode(string(addr.Under())) 405 return node.ID 406 } 407 408 // NewAddrFromNodeID constucts a BzzAddr from a discover.NodeID 409 // the overlay address is derived as the hash of the nodeID 410 func NewAddrFromNodeID(id discover.NodeID) *BzzAddr { 411 return &BzzAddr{ 412 OAddr: ToOverlayAddr(id.Bytes()), 413 UAddr: []byte(discover.NewNode(id, net.IP{127, 0, 0, 1}, 30303, 30303).String()), 414 } 415 } 416 417 // NewAddrFromNodeIDAndPort constucts a BzzAddr from a discover.NodeID and port uint16 418 // the overlay address is derived as the hash of the nodeID 419 func NewAddrFromNodeIDAndPort(id discover.NodeID, host net.IP, port uint16) *BzzAddr { 420 return &BzzAddr{ 421 OAddr: ToOverlayAddr(id.Bytes()), 422 UAddr: []byte(discover.NewNode(id, host, port, port).String()), 423 } 424 } 425 426 // ToOverlayAddr creates an overlayaddress from a byte slice 427 func ToOverlayAddr(id []byte) []byte { 428 return crypto.Keccak256(id) 429 }