| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package network | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2017-02-28 18:01:54 +02:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p/discover" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p/protocols" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/rpc" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/swarm/log" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/swarm/state" | 
					
						
							| 
									
										
										
										
											2018-02-23 14:19:59 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	DefaultNetworkID = 3 | 
					
						
							|  |  |  | 	// ProtocolMaxMsgSize maximum allowed message size | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	ProtocolMaxMsgSize = 10 * 1024 * 1024 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	// timeout for waiting | 
					
						
							|  |  |  | 	bzzHandshakeTimeout = 3000 * time.Millisecond | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // BzzSpec is the spec of the generic swarm handshake | 
					
						
							|  |  |  | var BzzSpec = &protocols.Spec{ | 
					
						
							|  |  |  | 	Name:       "bzz", | 
					
						
							| 
									
										
										
										
											2018-08-21 10:34:40 +02:00
										 |  |  | 	Version:    6, | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	MaxMsgSize: 10 * 1024 * 1024, | 
					
						
							|  |  |  | 	Messages: []interface{}{ | 
					
						
							|  |  |  | 		HandshakeMsg{}, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // DiscoverySpec is the spec for the bzz discovery subprotocols | 
					
						
							|  |  |  | var DiscoverySpec = &protocols.Spec{ | 
					
						
							|  |  |  | 	Name:       "hive", | 
					
						
							| 
									
										
										
										
											2018-07-13 17:40:55 +02:00
										 |  |  | 	Version:    5, | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	MaxMsgSize: 10 * 1024 * 1024, | 
					
						
							|  |  |  | 	Messages: []interface{}{ | 
					
						
							|  |  |  | 		peersMsg{}, | 
					
						
							|  |  |  | 		subPeersMsg{}, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Addr interface that peerPool needs | 
					
						
							|  |  |  | type Addr interface { | 
					
						
							|  |  |  | 	OverlayPeer | 
					
						
							|  |  |  | 	Over() []byte | 
					
						
							|  |  |  | 	Under() []byte | 
					
						
							|  |  |  | 	String() string | 
					
						
							|  |  |  | 	Update(OverlayAddr) OverlayAddr | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Peer interface represents an live peer connection | 
					
						
							|  |  |  | type Peer interface { | 
					
						
							|  |  |  | 	Addr                   // the address of a peer | 
					
						
							|  |  |  | 	Conn                   // the live connection (protocols.Peer) | 
					
						
							|  |  |  | 	LastActive() time.Time // last time active | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Conn interface represents an live peer connection | 
					
						
							|  |  |  | type Conn interface { | 
					
						
							|  |  |  | 	ID() discover.NodeID                                                                  // the key that uniquely identifies the Node for the peerPool | 
					
						
							|  |  |  | 	Handshake(context.Context, interface{}, func(interface{}) error) (interface{}, error) // can send messages | 
					
						
							| 
									
										
										
										
											2018-07-13 17:40:28 +02:00
										 |  |  | 	Send(context.Context, interface{}) error                                              // can send messages | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	Drop(error)                                                                           // disconnect this peer | 
					
						
							| 
									
										
										
										
											2018-07-13 17:40:28 +02:00
										 |  |  | 	Run(func(context.Context, interface{}) error) error                                   // the run function to run a protocol | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	Off() OverlayAddr | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // BzzConfig captures the config params used by the hive | 
					
						
							|  |  |  | type BzzConfig struct { | 
					
						
							|  |  |  | 	OverlayAddr  []byte // base address of the overlay network | 
					
						
							|  |  |  | 	UnderlayAddr []byte // node's underlay address | 
					
						
							|  |  |  | 	HiveParams   *HiveParams | 
					
						
							|  |  |  | 	NetworkID    uint64 | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 	LightNode    bool | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Bzz is the swarm protocol bundle | 
					
						
							|  |  |  | type Bzz struct { | 
					
						
							|  |  |  | 	*Hive | 
					
						
							|  |  |  | 	NetworkID    uint64 | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 	LightNode    bool | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	localAddr    *BzzAddr | 
					
						
							|  |  |  | 	mtx          sync.Mutex | 
					
						
							|  |  |  | 	handshakes   map[discover.NodeID]*HandshakeMsg | 
					
						
							|  |  |  | 	streamerSpec *protocols.Spec | 
					
						
							|  |  |  | 	streamerRun  func(*BzzPeer) error | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewBzz is the swarm protocol constructor | 
					
						
							|  |  |  | // arguments | 
					
						
							|  |  |  | // * bzz config | 
					
						
							|  |  |  | // * overlay driver | 
					
						
							|  |  |  | // * peer store | 
					
						
							|  |  |  | func NewBzz(config *BzzConfig, kad Overlay, store state.Store, streamerSpec *protocols.Spec, streamerRun func(*BzzPeer) error) *Bzz { | 
					
						
							|  |  |  | 	return &Bzz{ | 
					
						
							|  |  |  | 		Hive:         NewHive(config.HiveParams, kad, store), | 
					
						
							|  |  |  | 		NetworkID:    config.NetworkID, | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 		LightNode:    config.LightNode, | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 		localAddr:    &BzzAddr{config.OverlayAddr, config.UnderlayAddr}, | 
					
						
							|  |  |  | 		handshakes:   make(map[discover.NodeID]*HandshakeMsg), | 
					
						
							|  |  |  | 		streamerRun:  streamerRun, | 
					
						
							|  |  |  | 		streamerSpec: streamerSpec, | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // UpdateLocalAddr updates underlayaddress of the running node | 
					
						
							|  |  |  | func (b *Bzz) UpdateLocalAddr(byteaddr []byte) *BzzAddr { | 
					
						
							|  |  |  | 	b.localAddr = b.localAddr.Update(&BzzAddr{ | 
					
						
							|  |  |  | 		UAddr: byteaddr, | 
					
						
							|  |  |  | 		OAddr: b.localAddr.OAddr, | 
					
						
							|  |  |  | 	}).(*BzzAddr) | 
					
						
							|  |  |  | 	return b.localAddr | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // NodeInfo returns the node's overlay address | 
					
						
							|  |  |  | func (b *Bzz) NodeInfo() interface{} { | 
					
						
							|  |  |  | 	return b.localAddr.Address() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Protocols return the protocols swarm offers | 
					
						
							|  |  |  | // Bzz implements the node.Service interface | 
					
						
							|  |  |  | // * handshake/hive | 
					
						
							|  |  |  | // * discovery | 
					
						
							|  |  |  | func (b *Bzz) Protocols() []p2p.Protocol { | 
					
						
							|  |  |  | 	protocol := []p2p.Protocol{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Name:     BzzSpec.Name, | 
					
						
							|  |  |  | 			Version:  BzzSpec.Version, | 
					
						
							|  |  |  | 			Length:   BzzSpec.Length(), | 
					
						
							|  |  |  | 			Run:      b.runBzz, | 
					
						
							|  |  |  | 			NodeInfo: b.NodeInfo, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Name:     DiscoverySpec.Name, | 
					
						
							|  |  |  | 			Version:  DiscoverySpec.Version, | 
					
						
							|  |  |  | 			Length:   DiscoverySpec.Length(), | 
					
						
							|  |  |  | 			Run:      b.RunProtocol(DiscoverySpec, b.Hive.Run), | 
					
						
							|  |  |  | 			NodeInfo: b.Hive.NodeInfo, | 
					
						
							|  |  |  | 			PeerInfo: b.Hive.PeerInfo, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	if b.streamerSpec != nil && b.streamerRun != nil { | 
					
						
							|  |  |  | 		protocol = append(protocol, p2p.Protocol{ | 
					
						
							|  |  |  | 			Name:    b.streamerSpec.Name, | 
					
						
							|  |  |  | 			Version: b.streamerSpec.Version, | 
					
						
							|  |  |  | 			Length:  b.streamerSpec.Length(), | 
					
						
							|  |  |  | 			Run:     b.RunProtocol(b.streamerSpec, b.streamerRun), | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	return protocol | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // APIs returns the APIs offered by bzz | 
					
						
							|  |  |  | // * hive | 
					
						
							|  |  |  | // Bzz implements the node.Service interface | 
					
						
							|  |  |  | func (b *Bzz) APIs() []rpc.API { | 
					
						
							|  |  |  | 	return []rpc.API{{ | 
					
						
							|  |  |  | 		Namespace: "hive", | 
					
						
							|  |  |  | 		Version:   "3.0", | 
					
						
							|  |  |  | 		Service:   b.Hive, | 
					
						
							|  |  |  | 	}} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // RunProtocol is a wrapper for swarm subprotocols | 
					
						
							|  |  |  | // returns a p2p protocol run function that can be assigned to p2p.Protocol#Run field | 
					
						
							|  |  |  | // arguments: | 
					
						
							|  |  |  | // * p2p protocol spec | 
					
						
							|  |  |  | // * run function taking BzzPeer as argument | 
					
						
							|  |  |  | //   this run function is meant to block for the duration of the protocol session | 
					
						
							|  |  |  | //   on return the session is terminated and the peer is disconnected | 
					
						
							|  |  |  | // the protocol waits for the bzz handshake is negotiated | 
					
						
							|  |  |  | // the overlay address on the BzzPeer is set from the remote handshake | 
					
						
							|  |  |  | func (b *Bzz) RunProtocol(spec *protocols.Spec, run func(*BzzPeer) error) func(*p2p.Peer, p2p.MsgReadWriter) error { | 
					
						
							|  |  |  | 	return func(p *p2p.Peer, rw p2p.MsgReadWriter) error { | 
					
						
							|  |  |  | 		// wait for the bzz protocol to perform the handshake | 
					
						
							|  |  |  | 		handshake, _ := b.GetHandshake(p.ID()) | 
					
						
							|  |  |  | 		defer b.removeHandshake(p.ID()) | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-handshake.done: | 
					
						
							|  |  |  | 		case <-time.After(bzzHandshakeTimeout): | 
					
						
							|  |  |  | 			return fmt.Errorf("%08x: %s protocol timeout waiting for handshake on %08x", b.BaseAddr()[:4], spec.Name, p.ID().Bytes()[:4]) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 		if handshake.err != nil { | 
					
						
							|  |  |  | 			return fmt.Errorf("%08x: %s protocol closed: %v", b.BaseAddr()[:4], spec.Name, handshake.err) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 		// the handshake has succeeded so construct the BzzPeer and run the protocol | 
					
						
							|  |  |  | 		peer := &BzzPeer{ | 
					
						
							|  |  |  | 			Peer:       protocols.NewPeer(p, rw, spec), | 
					
						
							|  |  |  | 			localAddr:  b.localAddr, | 
					
						
							|  |  |  | 			BzzAddr:    handshake.peerAddr, | 
					
						
							|  |  |  | 			lastActive: time.Now(), | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 			LightNode:  handshake.LightNode, | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		log.Debug("peer created", "addr", handshake.peerAddr.String()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 		return run(peer) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // performHandshake implements the negotiation of the bzz handshake | 
					
						
							|  |  |  | // shared among swarm subprotocols | 
					
						
							|  |  |  | func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), bzzHandshakeTimeout) | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		close(handshake.done) | 
					
						
							|  |  |  | 		cancel() | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	rsh, err := p.Handshake(ctx, handshake, b.checkHandshake) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		handshake.err = err | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	handshake.peerAddr = rsh.(*HandshakeMsg).Addr | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 	handshake.LightNode = rsh.(*HandshakeMsg).LightNode | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // runBzz is the p2p protocol run function for the bzz base protocol | 
					
						
							|  |  |  | // that negotiates the bzz handshake | 
					
						
							|  |  |  | func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error { | 
					
						
							|  |  |  | 	handshake, _ := b.GetHandshake(p.ID()) | 
					
						
							|  |  |  | 	if !<-handshake.init { | 
					
						
							|  |  |  | 		return fmt.Errorf("%08x: bzz already started on peer %08x", b.localAddr.Over()[:4], ToOverlayAddr(p.ID().Bytes())[:4]) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	close(handshake.init) | 
					
						
							|  |  |  | 	defer b.removeHandshake(p.ID()) | 
					
						
							|  |  |  | 	peer := protocols.NewPeer(p, rw, BzzSpec) | 
					
						
							|  |  |  | 	err := b.performHandshake(peer, handshake) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 		log.Warn(fmt.Sprintf("%08x: handshake failed with remote peer %08x: %v", b.localAddr.Over()[:4], ToOverlayAddr(p.ID().Bytes())[:4], err)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 18:01:54 +02:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	// fail if we get another handshake | 
					
						
							|  |  |  | 	msg, err := rw.ReadMsg() | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	msg.Discard() | 
					
						
							|  |  |  | 	return errors.New("received multiple handshakes") | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // BzzPeer is the bzz protocol view of a protocols.Peer (itself an extension of p2p.Peer) | 
					
						
							|  |  |  | // implements the Peer interface and all interfaces Peer implements: Addr, OverlayPeer | 
					
						
							|  |  |  | type BzzPeer struct { | 
					
						
							|  |  |  | 	*protocols.Peer           // represents the connection for online peers | 
					
						
							|  |  |  | 	localAddr       *BzzAddr  // local Peers address | 
					
						
							|  |  |  | 	*BzzAddr                  // remote address -> implements Addr interface = protocols.Peer | 
					
						
							|  |  |  | 	lastActive      time.Time // time is updated whenever mutexes are releasing | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 	LightNode       bool | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | func NewBzzTestPeer(p *protocols.Peer, addr *BzzAddr) *BzzPeer { | 
					
						
							|  |  |  | 	return &BzzPeer{ | 
					
						
							|  |  |  | 		Peer:      p, | 
					
						
							|  |  |  | 		localAddr: addr, | 
					
						
							|  |  |  | 		BzzAddr:   NewAddrFromNodeID(p.ID()), | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Off returns the overlay peer record for offline persistence | 
					
						
							|  |  |  | func (p *BzzPeer) Off() OverlayAddr { | 
					
						
							|  |  |  | 	return p.BzzAddr | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // LastActive returns the time the peer was last active | 
					
						
							|  |  |  | func (p *BzzPeer) LastActive() time.Time { | 
					
						
							|  |  |  | 	return p.lastActive | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |  Handshake | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | * Version: 8 byte integer version of the protocol | 
					
						
							|  |  |  | * NetworkID: 8 byte integer network identifier | 
					
						
							|  |  |  | * Addr: the address advertised by the node including underlay and overlay connecctions | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | type HandshakeMsg struct { | 
					
						
							|  |  |  | 	Version   uint64 | 
					
						
							|  |  |  | 	NetworkID uint64 | 
					
						
							|  |  |  | 	Addr      *BzzAddr | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 	LightNode bool | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	// peerAddr is the address received in the peer handshake | 
					
						
							|  |  |  | 	peerAddr *BzzAddr | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	init chan bool | 
					
						
							|  |  |  | 	done chan struct{} | 
					
						
							|  |  |  | 	err  error | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // String pretty prints the handshake | 
					
						
							|  |  |  | func (bh *HandshakeMsg) String() string { | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 	return fmt.Sprintf("Handshake: Version: %v, NetworkID: %v, Addr: %v, LightNode: %v, peerAddr: %v", bh.Version, bh.NetworkID, bh.Addr, bh.LightNode, bh.peerAddr) | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Perform initiates the handshake and validates the remote handshake message | 
					
						
							|  |  |  | func (b *Bzz) checkHandshake(hs interface{}) error { | 
					
						
							|  |  |  | 	rhs := hs.(*HandshakeMsg) | 
					
						
							|  |  |  | 	if rhs.NetworkID != b.NetworkID { | 
					
						
							|  |  |  | 		return fmt.Errorf("network id mismatch %d (!= %d)", rhs.NetworkID, b.NetworkID) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 	if rhs.Version != uint64(BzzSpec.Version) { | 
					
						
							|  |  |  | 		return fmt.Errorf("version mismatch %d (!= %d)", rhs.Version, BzzSpec.Version) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // removeHandshake removes handshake for peer with peerID | 
					
						
							|  |  |  | // from the bzz handshake store | 
					
						
							|  |  |  | func (b *Bzz) removeHandshake(peerID discover.NodeID) { | 
					
						
							|  |  |  | 	b.mtx.Lock() | 
					
						
							|  |  |  | 	defer b.mtx.Unlock() | 
					
						
							|  |  |  | 	delete(b.handshakes, peerID) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // GetHandshake returns the bzz handhake that the remote peer with peerID sent | 
					
						
							|  |  |  | func (b *Bzz) GetHandshake(peerID discover.NodeID) (*HandshakeMsg, bool) { | 
					
						
							|  |  |  | 	b.mtx.Lock() | 
					
						
							|  |  |  | 	defer b.mtx.Unlock() | 
					
						
							|  |  |  | 	handshake, found := b.handshakes[peerID] | 
					
						
							|  |  |  | 	if !found { | 
					
						
							|  |  |  | 		handshake = &HandshakeMsg{ | 
					
						
							|  |  |  | 			Version:   uint64(BzzSpec.Version), | 
					
						
							|  |  |  | 			NetworkID: b.NetworkID, | 
					
						
							|  |  |  | 			Addr:      b.localAddr, | 
					
						
							| 
									
										
										
										
											2018-08-07 15:34:11 +02:00
										 |  |  | 			LightNode: b.LightNode, | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 			init:      make(chan bool, 1), | 
					
						
							|  |  |  | 			done:      make(chan struct{}), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// when handhsake is first created for a remote peer | 
					
						
							|  |  |  | 		// it is initialised with the init | 
					
						
							|  |  |  | 		handshake.init <- true | 
					
						
							|  |  |  | 		b.handshakes[peerID] = handshake | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return handshake, found | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // BzzAddr implements the PeerAddr interface | 
					
						
							|  |  |  | type BzzAddr struct { | 
					
						
							|  |  |  | 	OAddr []byte | 
					
						
							|  |  |  | 	UAddr []byte | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Address implements OverlayPeer interface to be used in Overlay | 
					
						
							|  |  |  | func (a *BzzAddr) Address() []byte { | 
					
						
							|  |  |  | 	return a.OAddr | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Over returns the overlay address | 
					
						
							|  |  |  | func (a *BzzAddr) Over() []byte { | 
					
						
							|  |  |  | 	return a.OAddr | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Under returns the underlay address | 
					
						
							|  |  |  | func (a *BzzAddr) Under() []byte { | 
					
						
							|  |  |  | 	return a.UAddr | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // ID returns the nodeID from the underlay enode address | 
					
						
							|  |  |  | func (a *BzzAddr) ID() discover.NodeID { | 
					
						
							|  |  |  | 	return discover.MustParseNode(string(a.UAddr)).ID | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // Update updates the underlay address of a peer record | 
					
						
							|  |  |  | func (a *BzzAddr) Update(na OverlayAddr) OverlayAddr { | 
					
						
							|  |  |  | 	return &BzzAddr{a.OAddr, na.(Addr).Under()} | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // String pretty prints the address | 
					
						
							|  |  |  | func (a *BzzAddr) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("%x <%s>", a.OAddr, a.UAddr) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RandomAddr is a utility method generating an address from a public key | 
					
						
							|  |  |  | func RandomAddr() *BzzAddr { | 
					
						
							|  |  |  | 	key, err := crypto.GenerateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic("unable to generate key") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pubkey := crypto.FromECDSAPub(&key.PublicKey) | 
					
						
							|  |  |  | 	var id discover.NodeID | 
					
						
							|  |  |  | 	copy(id[:], pubkey[1:]) | 
					
						
							|  |  |  | 	return NewAddrFromNodeID(id) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // NewNodeIDFromAddr transforms the underlay address to an adapters.NodeID | 
					
						
							|  |  |  | func NewNodeIDFromAddr(addr Addr) discover.NodeID { | 
					
						
							|  |  |  | 	log.Info(fmt.Sprintf("uaddr=%s", string(addr.Under()))) | 
					
						
							|  |  |  | 	node := discover.MustParseNode(string(addr.Under())) | 
					
						
							|  |  |  | 	return node.ID | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | // NewAddrFromNodeID constucts a BzzAddr from a discover.NodeID | 
					
						
							|  |  |  | // the overlay address is derived as the hash of the nodeID | 
					
						
							|  |  |  | func NewAddrFromNodeID(id discover.NodeID) *BzzAddr { | 
					
						
							|  |  |  | 	return &BzzAddr{ | 
					
						
							|  |  |  | 		OAddr: ToOverlayAddr(id.Bytes()), | 
					
						
							|  |  |  | 		UAddr: []byte(discover.NewNode(id, net.IP{127, 0, 0, 1}, 30303, 30303).String()), | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewAddrFromNodeIDAndPort constucts a BzzAddr from a discover.NodeID and port uint16 | 
					
						
							|  |  |  | // the overlay address is derived as the hash of the nodeID | 
					
						
							|  |  |  | func NewAddrFromNodeIDAndPort(id discover.NodeID, host net.IP, port uint16) *BzzAddr { | 
					
						
							|  |  |  | 	return &BzzAddr{ | 
					
						
							|  |  |  | 		OAddr: ToOverlayAddr(id.Bytes()), | 
					
						
							|  |  |  | 		UAddr: []byte(discover.NewNode(id, host, port, port).String()), | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-06-20 14:06:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ToOverlayAddr creates an overlayaddress from a byte slice | 
					
						
							|  |  |  | func ToOverlayAddr(id []byte) []byte { | 
					
						
							|  |  |  | 	return crypto.Keccak256(id) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | } |