Ejemplo n.º 1
0
    /// <summary>
    /// Unity event, in a real world scenario that would be listening over network
    /// </summary>
    /// <param name="m"></param>
    public void PeerMessage(Message m)
    {
        if (peers == null)
        {
            return;                // not ready yet
        }
        if (!peers.Contains(m.sender))
        {
            Debug.Log("New peer connected");
            peers.Add(m.sender);
        }

        switch (m.type)
        {
        case MessageType.QUERY_LATEST:
        {
            Message answer = new Message {
                sender = this, type = MessageType.RESPONSE_BLOCKCHAIN, data = new List <Block> {
                    blockchain.CloneLatestBlock()
                }
            };
            m.sender.SendMessage("PeerMessage", answer);
        }
        break;

        case MessageType.QUERY_ALL:
        {
            Message answer = new Message {
                sender = this, type = MessageType.RESPONSE_BLOCKCHAIN, data = blockchain.CloneChain()
            };
            m.sender.SendMessage("PeerMessage", answer);
        }
        break;

        case MessageType.QUERY_TRANSACTION_POOL:
        {
            Message answer = new Message {
                sender = this, type = MessageType.RESPONSE_TRANSACTION_POOL, data = blockchain.GetPooledTransactions()
            };
            m.sender.SendMessage("PeerMessage", answer);
        }
        break;

        case MessageType.RESPONSE_BLOCKCHAIN:
        {
            List <Block> receivedBlocks = (List <Block>)m.data;

            if (receivedBlocks == null || receivedBlocks.Count == 0)
            {
                Debug.LogWarning("Received empty blockchain data from peer");
                return;
            }

            if (receivedBlocks.Count == 1)
            {
                if (receivedBlocks.Last().previousHash == blockchain.LastBlock().hash&& receivedBlocks.Last().index == blockchain.LastBlock().index + 1)
                {
                    Debug.Log("Received a new block");
                    blockchain.StopMining();
                    blockchain.AddBlock(receivedBlocks.Last());
                }
                else if (receivedBlocks.Last().index != 0)        // only query if not genesis
                {
                    Debug.Log("Received a new block but the hash or index doesn't match. Querying the whole thing");
                    Message request = new Message {
                        sender = this, type = MessageType.QUERY_ALL, data = null
                    };
                    m.sender.SendMessage("PeerMessage", request);
                }
                else         // replace genesis with the exising one
                {
                    Debug.Log("Replace with existing genesis");
                    blockchain.ReplaceChain(receivedBlocks);
                }
            }
            else
            {
                if (Blockchain.GetAccumulatedDifficulty(receivedBlocks) > blockchain.GetAccumulatedDifficulty())
                {
                    Debug.Log("Received a new chain and its accumulated difficulty is higher, replacing...");
                    blockchain.ReplaceChain(receivedBlocks);
                }
                else
                {
                    Debug.Log("Received a new chain and whith lower accumulated difficulty, doing nothing");
                }
            }
        }
        break;

        case MessageType.RESPONSE_TRANSACTION_POOL:
        {
            Transaction[] receivedPoolTxs = (Transaction[])m.data;

            if (receivedPoolTxs == null)
            {
                Debug.LogError("Received null, expection transaction pool");
                return;
            }

            foreach (Transaction tx in receivedPoolTxs)
            {
                blockchain.AddToPool(tx);
            }
        }
        break;
        }
    }