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))
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 = BlockParser.ParseBlock(blockBytes); string.Format( "{0}: Receives block {1}.", GetID(), block.Header.Hash.ToHexString()) .Log(LogFile); if (IsStateIdle()) { // Received unsolicited block } else if (IsStateAwaitingBlock()) { BlockDownload.InsertBlock(block); if (BlockDownload.IsDownloadCompleted) { SignalProtocolTaskCompleted.Post(true); Cancellation = new CancellationTokenSource(); break; } Cancellation.CancelAfter( TIMEOUT_BLOCKDOWNLOAD_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 = BlockParser.ParseHeader( Payload, ref index); index += 1; if (!Blockchain.TryLock()) { break; } try { string.Format( "Received unsolicited header {0}", header.Hash.ToHexString()) .Log(LogFile); if (Blockchain.ContainsHeader(header.Hash)) { Header headerContained = Blockchain.HeaderTip; var headerDuplicates = new List <byte[]>(); int depthDuplicateAcceptedMax = 3; int depthDuplicate = 0; while (depthDuplicate < depthDuplicateAcceptedMax) { if (headerContained.Hash.IsEqual(header.Hash)) { if (headerDuplicates.Any(h => h.IsEqual(header.Hash))) { throw new ProtocolException( string.Format( "Received duplicate header {0} more than once.", header.Hash.ToHexString())); } headerDuplicates.Add(header.Hash); if (headerDuplicates.Count > depthDuplicateAcceptedMax) { headerDuplicates = headerDuplicates.Skip(1) .ToList(); } break; } if (headerContained.HeaderPrevious != null) { break; } headerContained = header.HeaderPrevious; depthDuplicate += 1; } if (depthDuplicate == depthDuplicateAcceptedMax) { throw new ProtocolException( string.Format( "Received duplicate header {0} with depth greater than {1}.", header.Hash.ToHexString(), depthDuplicateAcceptedMax)); } } else if (header.HashPrevious.IsEqual( Blockchain.HeaderTip.Hash)) { header.HeaderPrevious = Blockchain.HeaderTip; Blockchain.ValidateHeaders(header); await Blockchain.Network .SynchronizeUTXO(header, this); Blockchain.ReleaseLock(); break; } else { IsSynchronized = false; } } catch (Exception ex) { Blockchain.ReleaseLock(); throw ex; } Blockchain.ReleaseLock(); } else if (IsStateAwaitingHeader()) { if (countHeaders > 0) { header = BlockParser.ParseHeader( Payload, ref index); index += 1; HeaderDownload.InsertHeader(header); while (index < PayloadLength) { header = BlockParser.ParseHeader( Payload, ref index); index += 1; HeaderDownload.InsertHeader(header); } } string.Format( "{0}: Signal getheaders task complete.", GetID()) .Log(LogFile); SignalProtocolTaskCompleted.Post(true); Cancellation = new CancellationTokenSource(); break; } break; case "notfound": Console.WriteLine( "Command notfound not implemented yet."); break; case "inv": var invMessage = new InvMessage(Payload); if (invMessage.Inventories.First().IsTX()) { throw new ProtocolException( "Received TX inv message despite TX-disable signaled."); } break; default: // Send message unknown break; } } } catch (Exception ex) { FlagDispose = true; Cancellation.Cancel(); string.Format( "Peer {0} experienced error " + "in message listener: \n{1}", GetID(), "message: " + ex.Message + "stack trace: " + ex.StackTrace) .Log(LogFile); } }