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); }
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); }
public string Serialize() { return($"{BlobId.ValueString}:{string.Join(",", BlockHashes.Select(id => id.HashString))}"); }
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 ); } }
public void ReportBlockHash(Keccak blockHash) { BlockHashes.Add(blockHash); }
public IEnumerator <Block <T> > GetEnumerator() { return(BlockHashes.Select(hash => Blocks[hash]).GetEnumerator()); }
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 ); } }
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; } }
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 ); } }