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