code: func (p *peer) Handshake(network uint64, td *big.Int, head common.Hash, genesis common.Hash) error {
  	// Send out own handshake in a new thread
  	errc := make(chan error, 2)
  	var status statusData // safe to read after two values have been received from errc
  
  	go func() {
  		errc <- p2p.Send(p.rw, StatusMsg, &statusData{
  			ProtocolVersion: uint32(p.version),
  			NetworkId:       network,
  			TD:              td,
  			CurrentBlock:    head,
  			GenesisBlock:    genesis,
  		})
  	}()
  	go func() {
  		errc <- p.readStatus(network, &status, genesis)
  	}()
  	timeout := time.NewTimer(handshakeTimeout)
  	defer timeout.Stop()
  	for i := 0; i < 2; i++ {
  		select {
  		case err := <-errc:
  			if err != nil {
  				return err
  			}
  		case <-timeout.C:
  			return p2p.DiscReadTimeout
  		}
  	}
  	p.td, p.head = status.TD, status.CurrentBlock
  	return nil
  }
docs: // Handshake executes the eth protocol handshake, negotiating version number,
  // network IDs, difficulties, head and genesis blocks.