Exemple #1
0
        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);
        }
Exemple #2
0
        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()
            });
        }
Exemple #3
0
        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);
        }
Exemple #4
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))