private IEnumerable <Message> Execute(GetDataMessage msg) { var blockChain = _blockChainStore.GetBlockChain(); var messages = new List <Message>(); var notFoundInventory = new List <Inventory>(); if (msg.Inventories.Any()) { foreach (var inventory in msg.Inventories) { switch (inventory.Type) { case InventoryTypes.MSG_TX: var tx = MemoryPool.Instance().GetTransactions().FirstOrDefault(t => t.Transaction.GetTxId().SequenceEqual(inventory.Hash)); if (tx != null) { messages.Add(new TransactionMessage(tx.Transaction, msg.MessageHeader.Network)); continue; } break; case InventoryTypes.MSG_BLOCK: var block = blockChain.GetBlock(inventory.Hash); if (block != null) { messages.Add(new BlockMessage(block, msg.MessageHeader.Network)); continue; } break; } notFoundInventory.Add(inventory); } } if (notFoundInventory.Any()) { var notFoundMessage = new NotFoundMessage(notFoundInventory, msg.MessageHeader.Network); messages.Add(notFoundMessage); } return(messages); }
public Message Parse(byte[] payload) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } if (payload.Length < 24) { throw new ParseMessageException(ErrorCodes.InvalidCommandLength); } var header = payload.Take(40); // Extract the header. var startStringPayload = header.Take(4); var network = Networks.MainNet; if (startStringPayload.SequenceEqual(new byte[] { 0xf9, 0xbe, 0xb4, 0xd9 })) { network = Networks.MainNet; } else if (startStringPayload.SequenceEqual(new byte[] { 0x0b, 0x11, 0x09, 0x07 })) { network = Networks.TestNet; } else if (startStringPayload.SequenceEqual(new byte[] { 0xfa, 0xbf, 0xb5, 0xda })) { network = Networks.RegTest; } else { throw new ParseMessageException(ErrorCodes.InvalidStartString); } var commandNamePayload = header.Skip(4).Take(12).Where(b => b != 0x00).ToArray(); var commandName = System.Text.Encoding.ASCII.GetString(commandNamePayload); var ipv6 = header.Skip(16).Take(16); var payloadSizePayload = header.Skip(32).Take(4).ToArray(); var payloadSize = BitConverter.ToInt32(payloadSizePayload, 0); var checkSum = header.Skip(36).Take(4); byte[] contentPayload = null; if (payloadSize > 0) { contentPayload = payload.Skip(40).Take(payloadSize).ToArray(); SHA256 mySHA256 = SHA256.Create(); var newCheckSum = mySHA256.ComputeHash(mySHA256.ComputeHash(contentPayload)).Take(4); if (!newCheckSum.SequenceEqual(checkSum)) { throw new ParseMessageException(ErrorCodes.InvalidChecksum); } } else if (!checkSum.SequenceEqual(new byte[] { 0x5d, 0xf6, 0xe0, 0xe2 })) { throw new ParseMessageException(ErrorCodes.InvalidChecksum); } if (!Constants.MessageNameLst.Contains(commandName)) { throw new ParseMessageException(ErrorCodes.InvalidCommandName); } Message message = null; if (commandName == Constants.MessageNames.Ping) { var nonce = BitConverter.ToUInt64(contentPayload, 0); message = new PingMessage(nonce, network); } else if (commandName == Constants.MessageNames.Addr) { message = AddrMessage.Deserialize(contentPayload, network); } else if (commandName == Constants.MessageNames.Version) { message = VersionMessage.Deserialize(contentPayload, network); } else if (commandName == Constants.MessageNames.Verack) { message = new VerackMessage(network); } else if (commandName == Constants.MessageNames.GetAddr) { message = new GetAddressMessage(network); } else if (commandName == Constants.MessageNames.Inventory) { message = InventoryMessage.Deserialize(contentPayload, network); } else if (commandName == Constants.MessageNames.Transaction) { message = TransactionMessage.Deserialize(contentPayload, network, Transactions.TransactionTypes.NoneCoinbase); } else if (commandName == Constants.MessageNames.Pong) { var nonce = BitConverter.ToUInt64(contentPayload, 0); message = new PongMessage(nonce, network); } else if (commandName == Constants.MessageNames.MemPool) { message = new MemPoolMessage(network); } else if (commandName == Constants.MessageNames.GetData) { message = GetDataMessage.Deserialize(contentPayload, network); } else if (commandName == Constants.MessageNames.Block) { message = BlockMessage.Deserialize(contentPayload, network); } else if (commandName == Constants.MessageNames.GetBlocks) { message = GetBlocksMessage.Deserialize(contentPayload, network); } else if (commandName == Constants.MessageNames.NotFound) { message = NotFoundMessage.Deserialize(contentPayload, network); } message.MessageHeader.Ipv6 = ipv6.ToArray(); return(message); }