/// <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; } }