Example #1
0
            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))
Example #2
0
                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);
                    }
                }