예제 #1
0
        public void Decode()
        {
            BlockHash[] blockHashes = GenerateRandomBlockHashes(100L).ToArray();
            var         msg         = new BlockHashes(123, blockHashes);

            Assert.Equal(123, msg.StartIndex);
            Assert.Equal(blockHashes, msg.Hashes);
            var privKey               = new PrivateKey();
            AppProtocolVersion ver    = AppProtocolVersion.Sign(privKey, 3);
            Peer         peer         = new BoundPeer(privKey.PublicKey, new DnsEndPoint("0.0.0.0", 1234));
            var          messageCodec = new NetMQMessageCodec();
            NetMQMessage encoded      = messageCodec.Encode(
                msg,
                privKey,
                peer,
                DateTimeOffset.UtcNow,
                ver);
            BlockHashes restored = (BlockHashes)messageCodec.Decode(
                encoded,
                true,
                (b, p, a) => { },
                null);

            Assert.Equal(msg.StartIndex, restored.StartIndex);
            Assert.Equal(msg.Hashes, restored.Hashes);
        }
예제 #2
0
        public void DataFrames()
        {
            HashDigest <SHA256>[] blockHashes = GenerateRandomBlockHashes(100L).ToArray();
            var msg = new BlockHashes(123, blockHashes);

            Assert.Equal(123, msg.StartIndex);
            Assert.Equal(blockHashes, msg.Hashes);
            var privKey            = new PrivateKey();
            AppProtocolVersion ver = AppProtocolVersion.Sign(privKey, 3);
            Peer peer = new BoundPeer(privKey.PublicKey, new DnsEndPoint("0.0.0.0", 1234), ver);

            NetMQFrame[] frames   = msg.ToNetMQMessage(privKey, peer).Skip(3).ToArray();
            var          restored = new BlockHashes(frames);

            Assert.Equal(msg.StartIndex, restored.StartIndex);
            Assert.Equal(msg.Hashes, restored.Hashes);
        }
예제 #3
0
 public string Serialize()
 {
     return($"{BlobId.ValueString}:{string.Join(",", BlockHashes.Select(id => id.HashString))}");
 }
예제 #4
0
        private void ProcessMessageHandler(object target, Message message)
        {
            switch (message)
            {
            case Ping ping:
            {
                _logger.Debug($"Received a {nameof(Ping)} message.");

                // This case can be dealt in Transport.
                var pong = new Pong()
                {
                    Identity = ping.Identity,
                };

                Transport.ReplyMessage(pong);
                break;
            }

            case GetChainStatus getChainStatus:
            {
                _logger.Debug($"Received a {nameof(GetChainStatus)} message.");

                // This is based on the assumption that genesis block always exists.
                var chainStatus = new ChainStatus(
                    BlockChain.Genesis.Hash,
                    BlockChain.Tip.Index,
                    BlockChain.Tip.TotalDifficulty)
                {
                    Identity = getChainStatus.Identity,
                };

                Transport.ReplyMessage(chainStatus);
                break;
            }

            case FindNeighbors _:
                _logger.Debug($"Received a {nameof(FindNeighbors)} message.");
                break;

            case GetBlockHashes getBlockHashes:
            {
                BlockChain.FindNextHashes(
                    getBlockHashes.Locator,
                    getBlockHashes.Stop,
                    FindNextHashesChunkSize
                    ).Deconstruct(
                    out long?offset,
                    out IReadOnlyList <HashDigest <SHA256> > hashes
                    );
                var reply = new BlockHashes(offset, hashes)
                {
                    Identity = getBlockHashes.Identity,
                };
                Transport.ReplyMessage(reply);
                break;
            }

            case GetRecentStates getRecentStates:
                TransferRecentStates(getRecentStates);
                break;

            case GetBlocks getBlocks:
                TransferBlocks(getBlocks);
                break;

            case GetTxs getTxs:
                TransferTxs(getTxs);
                break;

            case TxIds txIds:
                ProcessTxIds(txIds);
                break;

            case BlockHashes _:
                _logger.Error($"{nameof(BlockHashes)} messages are only for IBD.");
                break;

            case BlockHeaderMessage blockHeader:
                Task.Run(
                    async() => await ProcessBlockHeader(blockHeader, _cancellationToken),
                    _cancellationToken
                    );
                break;

            case GetBlockStates getBlockStates:
                TransferBlockStates(getBlockStates);
                break;

            default:
                throw new InvalidMessageException(
                          $"Failed to handle message: {message}",
                          message
                          );
            }
        }
예제 #5
0
 public void ReportBlockHash(Keccak blockHash)
 {
     BlockHashes.Add(blockHash);
 }
예제 #6
0
 public IEnumerator <Block <T> > GetEnumerator()
 {
     return(BlockHashes.Select(hash => Blocks[hash]).GetEnumerator());
 }
예제 #7
0
        private void ProcessMessageHandler(object target, Message message)
        {
            switch (message)
            {
            case Ping _:
            case FindNeighbors _:
                break;

            case GetChainStatus getChainStatus:
            {
                _logger.Debug($"Received a {nameof(GetChainStatus)} message.");

                // This is based on the assumption that genesis block always exists.
                Block <T> tip         = BlockChain.Tip;
                var       chainStatus = new ChainStatus(
                    tip.ProtocolVersion,
                    BlockChain.Genesis.Hash,
                    tip.Index,
                    tip.Hash,
                    tip.TotalDifficulty
                    )
                {
                    Identity = getChainStatus.Identity,
                };

                Transport.ReplyMessage(chainStatus);
                break;
            }

            case GetBlockHashes getBlockHashes:
            {
                const string msg =
                    "Received a " + nameof(GetBlockHashes) + " message " +
                    "(locator: {Locator}, stop: {Stop}).";
                BlockHash[] locatorArray = getBlockHashes.Locator.ToArray();
                _logger.Debug(msg, locatorArray, getBlockHashes.Stop);
                BlockChain.FindNextHashes(
                    getBlockHashes.Locator,
                    getBlockHashes.Stop,
                    FindNextHashesChunkSize
                    ).Deconstruct(
                    out long?offset,
                    out IReadOnlyList <BlockHash> hashes
                    );
                const string resultMsg =
                    "Found hashes after the branchpoint (locator: {Locator}, stop: {Stop}): " +
                    "{Hashes} (offset: {Offset}.";
                _logger.Debug(resultMsg, locatorArray, getBlockHashes.Stop, hashes, offset);
                var reply = new BlockHashes(offset, hashes)
                {
                    Identity = getBlockHashes.Identity,
                };
                Transport.ReplyMessage(reply);
                break;
            }

            case GetBlocks getBlocks:
                TransferBlocks(getBlocks);
                break;

            case GetTxs getTxs:
                TransferTxs(getTxs);
                break;

            case TxIds txIds:
                ProcessTxIds(txIds);
                break;

            case BlockHashes _:
                _logger.Error($"{nameof(BlockHashes)} messages are only for IBD.");
                break;

            case BlockHeaderMessage blockHeader:
                Task.Run(
                    async() => await ProcessBlockHeader(blockHeader, _cancellationToken),
                    _cancellationToken
                    );
                break;

            default:
                throw new InvalidMessageException(
                          $"Failed to handle message: {message}",
                          message
                          );
            }
        }
예제 #8
0
        private async Task ProcessMessageAsync <T>(
            Blockchain <T> blockchain,
            Message message,
            CancellationToken cancellationToken)
            where T : IAction
        {
            switch (message)
            {
            case Ping ping:
            {
                _logger.Debug($"Ping received.");
                var reply = new Pong
                {
                    Identity = ping.Identity,
                };
                await ReplyAsync(reply, cancellationToken);

                break;
            }

            case Messages.PeerSetDelta peerSetDelta:
            {
                _deltas.Enqueue(peerSetDelta.Delta);
                break;
            }

            case GetBlockHashes getBlockHashes:
            {
                IEnumerable <HashDigest <SHA256> > hashes =
                    blockchain.FindNextHashes(
                        getBlockHashes.Locator,
                        getBlockHashes.Stop,
                        500);
                var reply = new BlockHashes(hashes)
                {
                    Identity = getBlockHashes.Identity,
                };
                await ReplyAsync(reply, cancellationToken);

                break;
            }

            case GetBlocks getBlocks:
            {
                await TransferBlocks(
                    blockchain, getBlocks, cancellationToken);

                break;
            }

            case GetTxs getTxs:
            {
                await TransferTxs(
                    blockchain, getTxs, cancellationToken);

                break;
            }

            case TxIds txIds:
            {
                await ProcessTxIds(
                    txIds, blockchain, cancellationToken);

                break;
            }

            default:
                Trace.Fail($"Can't handle message. [{message}]");
                break;
            }
        }
예제 #9
0
        private async Task ProcessMessageHandlerAsync(Message message)
        {
            switch (message)
            {
            case Ping _:
            case FindNeighbors _:
                break;

            case GetChainStatus getChainStatus:
            {
                _logger.Debug(
                    "Received a {MessageType} message.",
                    nameof(Messages.GetChainStatus));

                // This is based on the assumption that genesis block always exists.
                Block <T> tip         = BlockChain.Tip;
                var       chainStatus = new ChainStatus(
                    tip.ProtocolVersion,
                    BlockChain.Genesis.Hash,
                    tip.Index,
                    tip.Hash,
                    tip.TotalDifficulty
                    )
                {
                    Identity = getChainStatus.Identity,
                };

                await Transport.ReplyMessageAsync(chainStatus, default);

                break;
            }

            case GetBlockHashes getBlockHashes:
            {
                _logger.Debug(
                    "Received a {MessageType} message (stop: {Stop}).",
                    nameof(Messages.GetBlockHashes),
                    getBlockHashes.Stop);
                BlockChain.FindNextHashes(
                    getBlockHashes.Locator,
                    getBlockHashes.Stop,
                    FindNextHashesChunkSize
                    ).Deconstruct(
                    out long?offset,
                    out IReadOnlyList <BlockHash> hashes
                    );
                _logger.Debug(
                    "Found {HashCount} hashes after the branchpoint (offset: {Offset}) " +
                    "with locator [{LocatorHead}, ...] (stop: {Stop}).",
                    hashes.Count,
                    offset,
                    getBlockHashes.Locator.FirstOrDefault(),
                    getBlockHashes.Stop);
                var reply = new BlockHashes(offset, hashes)
                {
                    Identity = getBlockHashes.Identity,
                };

                await Transport.ReplyMessageAsync(reply, default);

                break;
            }

            case GetBlocks getBlocks:
                await TransferBlocksAsync(getBlocks);

                break;

            case GetTxs getTxs:
                await TransferTxsAsync(getTxs);

                break;

            case TxIds txIds:
                await Transport.ReplyMessageAsync(
                    new Pong { Identity = txIds.Identity },
                    default);

                ProcessTxIds(txIds);
                break;

            case BlockHashes _:
                _logger.Error(
                    "{MessageType} messages are only for IBD.",
                    nameof(Messages.BlockHashes));
                break;

            case BlockHeaderMessage blockHeader:
                await Transport.ReplyMessageAsync(
                    new Pong { Identity = blockHeader.Identity },
                    default);

                ProcessBlockHeader(blockHeader);
                break;

            default:
                throw new InvalidMessageException(
                          $"Failed to handle message: {message}",
                          message
                          );
            }
        }