Exemplo n.º 1
0
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)))
	}
}
Exemplo n.º 2
0
// 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()
}