Handshake executes the cpchain protocol handshake, negotiating version number, network IDs, head and genesis blocks.
(network uint64, ht *big.Int, head common.Hash, genesis common.Hash, isMinerOrValidator bool)
| 333 | // Handshake executes the cpchain protocol handshake, negotiating version number, |
| 334 | // network IDs, head and genesis blocks. |
| 335 | func (p *peer) Handshake(network uint64, ht *big.Int, head common.Hash, genesis common.Hash, isMinerOrValidator bool) (bool, error) { |
| 336 | |
| 337 | log.Debug("handshaking with remote cpc peer...", "network", network, "blockchain hight", ht.Uint64(), "head", head.Hex(), "genesis", genesis.Hex(), "is Miner", isMinerOrValidator) |
| 338 | |
| 339 | errc := make(chan error, 2) |
| 340 | var status statusData // safe to read after two values have been received from errc |
| 341 | |
| 342 | // Send out own handshake in a new thread |
| 343 | go func() { |
| 344 | sd := statusData{ |
| 345 | ProtocolVersion: uint32(p.version), |
| 346 | NetworkId: network, |
| 347 | Height: ht, |
| 348 | CurrentBlock: head, |
| 349 | GenesisBlock: genesis, |
| 350 | IsMinerOrValidator: isMinerOrValidator, |
| 351 | } |
| 352 | errc <- p2p.Send(p.rw, StatusMsg, &sd) |
| 353 | }() |
| 354 | |
| 355 | // Reads the status of remote peer from the opposite side. |
| 356 | go func() { |
| 357 | var err error |
| 358 | for i := 0; i < handshakeReadCnt; i++ { |
| 359 | time.Sleep(handshakeTimeout / handshakeReadCnt) |
| 360 | err = p.readStatus(network, &status, genesis) |
| 361 | if err == nil { |
| 362 | break |
| 363 | } |
| 364 | if err != io.EOF { |
| 365 | break |
| 366 | } |
| 367 | } |
| 368 | errc <- err |
| 369 | }() |
| 370 | |
| 371 | timeout := time.NewTimer(handshakeTimeout) |
| 372 | defer timeout.Stop() |
| 373 | |
| 374 | for i := 0; i < 2; i++ { |
| 375 | select { |
| 376 | case err := <-errc: |
| 377 | if err != nil { |
| 378 | return false, err |
| 379 | } |
| 380 | case <-timeout.C: |
| 381 | return false, p2p.DiscReadTimeout |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | p.ht, p.head = status.Height, status.CurrentBlock |
| 386 | return status.IsMinerOrValidator, nil |
| 387 | } |
| 388 | |
| 389 | func (p *peer) readStatus(network uint64, status *statusData, genesis common.Hash) (err error) { |
| 390 | msg, err := p.rw.ReadMsg() |