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 void Handle(GetDataMessage message) { List <T> result = new List <T>(); if (File.Exists(this._tempFileName)) { string data = ""; using (this._locker.Acquire(Consts.DefaultWaitTime)) { data = File.ReadAllText(this._tempFileName, Encoding.UTF8); } result = JsonConvert.DeserializeObject <List <T> >(data); } message.Receiver.Send( new DataResultMessage <T> { Data = message.Count > -1 ? result.Skip(message.StartsFrom).Take(message.Count).ToList() : result.Skip(message.StartsFrom).ToList() }); }
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); }
public async Task StartMessageListener() { try { while (true) { await ReadMessage(Cancellation.Token); string.Format( "{0} received message {1}", GetID(), Command) .Log(LogFile); switch (Command) { case "ping": await SendMessage(new PongMessage( BitConverter.ToUInt64(Payload, 0))); break; case "addr": AddressMessage addressMessage = new AddressMessage(Payload); break; case "sendheaders": await SendMessage(new SendHeadersMessage()); break; case "feefilter": FeeFilterMessage feeFilterMessage = new FeeFilterMessage(Payload); FeeFilterValue = feeFilterMessage.FeeFilterValue; break; case "block": byte[] blockBytes = Payload .Take(PayloadLength) .ToArray(); Block block = ParserToken.ParseBlock(blockBytes); if (IsStateIdle()) { string.Format( "{0}: Receives unsolicited block {1}.", GetID(), block.Header.Hash.ToHexString()) .Log(LogFile); Console.Beep(); if (!Blockchain.TryLock()) { break; } try { ProcessHeaderUnsolicited( block.Header, out bool flagHeaderExtendsChain); if (flagHeaderExtendsChain) { if (!Blockchain.TryInsertBlock( block, flagValidateHeader: true)) { // Blockchain insert sollte doch einfach Ex. schmeissen } } } catch (Exception ex) { Blockchain.ReleaseLock(); throw ex; } Blockchain.ReleaseLock(); } else if (IsStateAwaitingBlockDownload()) { BlockDownload.InsertBlock(block); if (BlockDownload.IsDownloadCompleted) { SignalProtocolTaskCompleted.Post(true); lock (LOCK_StateProtocol) { State = StateProtocol.IDLE; } break; } Cancellation.CancelAfter( TIMEOUT_RESPONSE_MILLISECONDS); } break; case "headers": Header header = null; int index = 0; int countHeaders = VarInt.GetInt32( Payload, ref index); string.Format( "{0}: Receiving {1} headers.", GetID(), countHeaders) .Log(LogFile); if (IsStateIdle()) { header = Token.ParseHeader( Payload, ref index); string.Format( "Received unsolicited header {0}", header.Hash.ToHexString()) .Log(LogFile); index += 1; if (!Blockchain.TryLock()) { break; } try { ProcessHeaderUnsolicited( header, out bool flagHeaderExtendsChain); if (flagHeaderExtendsChain) { List <Inventory> inventories = new() { new Inventory( InventoryType.MSG_BLOCK, header.Hash) }; SendMessage(new GetDataMessage(inventories)); } } catch (Exception ex) { Blockchain.ReleaseLock(); throw ex; } Blockchain.ReleaseLock(); } else if (IsStateGetHeaders()) { if (countHeaders > 0) { while (index < PayloadLength) { header = Token.ParseHeader( Payload, ref index); index += 1; HeaderDownload.InsertHeader(header, Token); } } SignalProtocolTaskCompleted.Post(true); } break; case "notfound": Debug.WriteLine( "Command notfound not implemented yet."); break; case "inv": var invMessage = new InvMessage(Payload); var getDataMessage = new GetDataMessage( invMessage.Inventories); break; case "getdata": getDataMessage = new GetDataMessage(Payload); foreach (Inventory inventory in getDataMessage.Inventories) { if (inventory.Type == InventoryType.MSG_TX) { if (Token.TryRequestTX( inventory.Hash, out byte[] tXRaw))