func (self *Peer) FetchBlocks() { blockPool := self.ethereum.blockPool hashes := blockPool.Take(100, self) if len(hashes) > 0 { self.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlocksTy, ethutil.ByteSliceToInterface(hashes))) } }
// Inbound handler. Inbound messages are received here and passed to the appropriate methods func (p *Peer) HandleInbound() { for atomic.LoadInt32(&p.disconnect) == 0 { // HMM? time.Sleep(50 * time.Millisecond) // Wait for a message from the peer msgs, err := ethwire.ReadMessages(p.conn) if err != nil { peerlogger.Debugln(err) } for _, msg := range msgs { peerlogger.DebugDetailf("(%v) => %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data) switch msg.Type { case ethwire.MsgHandshakeTy: // Version message p.handleHandshake(msg) if p.caps.IsCap(CapPeerDiscTy) { p.QueueMessage(ethwire.NewMessage(ethwire.MsgGetPeersTy, "")) } case ethwire.MsgDiscTy: p.Stop() peerlogger.Infoln("Disconnect peer: ", DiscReason(msg.Data.Get(0).Uint())) case ethwire.MsgPingTy: // Respond back with pong p.QueueMessage(ethwire.NewMessage(ethwire.MsgPongTy, "")) case ethwire.MsgPongTy: // If we received a pong back from a peer we set the // last pong so the peer handler knows this peer is still // active. p.lastPong = time.Now().Unix() p.pingTime = time.Since(p.pingStartTime) case ethwire.MsgTxTy: // If the message was a transaction queue the transaction // in the TxPool where it will undergo validation and // processing when a new block is found for i := 0; i < msg.Data.Len(); i++ { tx := ethchain.NewTransactionFromValue(msg.Data.Get(i)) p.ethereum.TxPool().QueueTransaction(tx) } case ethwire.MsgGetPeersTy: // Peer asked for list of connected peers p.pushPeers() case ethwire.MsgPeersTy: // Received a list of peers (probably because MsgGetPeersTy was send) data := msg.Data // Create new list of possible peers for the ethereum to process peers := make([]string, data.Len()) // Parse each possible peer for i := 0; i < data.Len(); i++ { value := data.Get(i) peers[i] = unpackAddr(value.Get(0), value.Get(1).Uint()) } // Connect to the list of peers p.ethereum.ProcessPeerList(peers) case ethwire.MsgGetTxsTy: // Get the current transactions of the pool txs := p.ethereum.TxPool().CurrentTransactions() // Get the RlpData values from the txs txsInterface := make([]interface{}, len(txs)) for i, tx := range txs { txsInterface[i] = tx.RlpData() } // Broadcast it back to the peer p.QueueMessage(ethwire.NewMessage(ethwire.MsgTxTy, txsInterface)) case ethwire.MsgGetBlockHashesTy: if msg.Data.Len() < 2 { peerlogger.Debugln("err: argument length invalid ", msg.Data.Len()) } hash := msg.Data.Get(0).Bytes() amount := msg.Data.Get(1).Uint() hashes := p.ethereum.BlockChain().GetChainHashesFromHash(hash, amount) p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockHashesTy, ethutil.ByteSliceToInterface(hashes))) case ethwire.MsgGetBlocksTy: // Limit to max 300 blocks max := int(math.Min(float64(msg.Data.Len()), 300.0)) var blocks []interface{} for i := 0; i < max; i++ { hash := msg.Data.Get(i).Bytes() block := p.ethereum.BlockChain().GetBlock(hash) if block != nil { blocks = append(blocks, block.Value().Raw()) } } p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, blocks)) case ethwire.MsgBlockHashesTy: p.catchingUp = true blockPool := p.ethereum.blockPool foundCommonHash := false it := msg.Data.NewIterator() for it.Next() { hash := it.Value().Bytes() if blockPool.HasCommonHash(hash) { foundCommonHash = true break } blockPool.AddHash(hash) p.lastReceivedHash = hash p.lastBlockReceived = time.Now() } if foundCommonHash { p.FetchBlocks() } else { p.FetchHashes() } case ethwire.MsgBlockTy: p.catchingUp = true blockPool := p.ethereum.blockPool it := msg.Data.NewIterator() for it.Next() { block := ethchain.NewBlockFromRlpValue(it.Value()) blockPool.SetBlock(block) p.lastBlockReceived = time.Now() } linked := blockPool.CheckLinkAndProcess(func(block *ethchain.Block) { p.ethereum.StateManager().Process(block, false) }) if !linked { p.FetchBlocks() } } } } p.Stop() }