public Task ProcessAnnouncement(BlockAnnouncement announcement, ServerCallContext context) { if (announcement?.BlockHash == null) { Logger.LogWarning($"Received null announcement or header from {context.GetPeerInfo()}."); return(Task.CompletedTask); } Logger.LogDebug( $"Received announce, block hash: {announcement.BlockHash}, block height: {announcement.BlockHeight} from {context.GetPeerInfo()}."); var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey()); if (peer == null) { // if peer already removed, drop. return(Task.CompletedTask); } if (!peer.TryAddKnownBlock(announcement.BlockHash)) { return(Task.CompletedTask); } if (peer.SyncState != SyncState.Finished) { peer.SyncState = SyncState.Finished; } _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, context.GetPublicKey())); return(Task.CompletedTask); }
public void Peer_AddKnowBlock_Test() { //fork clean hash var announcement = new BlockAnnouncement { HasFork = true }; _grpcPeer.AddKnowBlock(announcement); _grpcPeer.RecentBlockHeightAndHashMappings.Count().ShouldBe(0); for (var i = 0; i < 10; i++) { _grpcPeer.AddKnowBlock(new BlockAnnouncement { BlockHash = Hash.FromString($"height-{i+1}"), BlockHeight = i + 1, HasFork = false }); _grpcPeer.RecentBlockHeightAndHashMappings.Count().ShouldBe(i + 1); } //over max value _grpcPeer.AddKnowBlock(new BlockAnnouncement { BlockHash = Hash.FromString($"random-hash"), BlockHeight = 20, HasFork = false }); _grpcPeer.RecentBlockHeightAndHashMappings.Count().ShouldBe(10); }
public async Task HandleAnnounceReceiveEventAsync_IrreversibleBlockIndex_IsNull() { var an = new BlockAnnouncement(); var sendKey = string.Empty; var announcementData = new AnnouncementReceivedEventData(an, sendKey); await _dpoSAnnouncementReceivedEventDataHandler.HandleEventAsync(announcementData); }
public void EnqueueAnnouncement(BlockAnnouncement announcement, Action <NetworkException> sendCallback) { if (!IsReady) { throw new NetworkException($"Dropping announcement, peer is not ready - {this}.", NetworkExceptionType.NotConnected); } _sendAnnouncementJobs.Post(new StreamJob { BlockAnnouncement = announcement, SendCallback = sendCallback }); }
public async Task HandleAnnounceReceiveEventAsync_IrreversibleBlockIndex_SureAmountEnough() { var block = await GenerateNewBlockAndAnnouncementToPeers(3); var an = new BlockAnnouncement { BlockHash = block.GetHash(), BlockHeight = block.Height }; var sendKey = CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); var announcementData = new AnnouncementReceivedEventData(an, sendKey); await _dpoSAnnouncementReceivedEventDataHandler.HandleEventAsync(announcementData); }
/// <summary> /// This method is called when a peer wants to broadcast an announcement. /// </summary> public override async Task <VoidReply> SendAnnouncement(BlockAnnouncement an, ServerCallContext context) { try { await ProcessAnnouncement(an, context); } catch (Exception e) { Logger.LogError(e, $"Process announcement error: {context.GetPeerInfo()}"); throw; } return(new VoidReply()); }
public Task BroadcastAnnounceAsync(BlockHeader blockHeader, bool hasFork) { var blockHash = blockHeader.GetHash(); if (!TryAddKnownBlock(blockHeader)) { return(Task.CompletedTask); } if (IsOldBlock(blockHeader)) { return(Task.CompletedTask); } var announce = new BlockAnnouncement { BlockHash = blockHash, BlockHeight = blockHeader.Height, HasFork = hasFork }; var beforeEnqueue = TimestampHelper.GetUtcNow(); _taskQueueManager.Enqueue(async() => { var execTime = TimestampHelper.GetUtcNow(); if (execTime > beforeEnqueue + TimestampHelper.DurationFromMilliseconds(NetworkConstants.AnnouncementQueueJobTimeout)) { Logger.LogWarning($"Announcement too old: {execTime - beforeEnqueue}"); return; } foreach (var peer in _peerPool.GetPeers()) { try { await peer.SendAnnouncementAsync(announce); } catch (NetworkException ex) { Logger.LogError(ex, $"Error while announcing to {peer}."); await HandleNetworkException(peer, ex); } } }, NetworkConstants.AnnouncementBroadcastQueueName); return(Task.CompletedTask); }
public async Task HandleEventAsync(PeerConnectedEventData eventData) { Logger.LogDebug($"Peer connection event {eventData.NodeInfo}"); await _peerDiscoveryService.AddNodeAsync(eventData.NodeInfo); var blockAnnouncement = new BlockAnnouncement { BlockHash = eventData.BestChainHash, BlockHeight = eventData.BestChainHeight }; var announcement = new AnnouncementReceivedEventData(blockAnnouncement, eventData.NodeInfo.Pubkey.ToHex()); await LocalEventBus.PublishAsync(announcement); }
public Task <bool> ValidateAnnouncementBeforeSyncAsync(Chain chain, BlockAnnouncement blockAnnouncement, string senderPubKey) { if (!TryCacheNewAnnouncement(blockAnnouncement.BlockHash, blockAnnouncement.BlockHeight, senderPubKey)) { return(Task.FromResult(false)); } if (blockAnnouncement.BlockHeight <= chain.LastIrreversibleBlockHeight) { Logger.LogWarning( $"Receive lower header {{ hash: {blockAnnouncement.BlockHash}, height: {blockAnnouncement.BlockHeight} }} ignore."); return(Task.FromResult(false)); } return(Task.FromResult(true)); }
public async Task ValidateAnnouncement_LessThenLIBHeight() { var chain = await _blockchainService.GetChainAsync(); var blockAnnouncement = new BlockAnnouncement { BlockHash = Hash.FromString("SyncBlockHash"), BlockHeight = chain.LastIrreversibleBlockHeight }; var validateResult = await _blockSyncValidationService.ValidateAnnouncementAsync(chain, blockAnnouncement, GetEncodedPubKeyString()); validateResult.ShouldBeFalse(); }
public async Task Announce_ShouldAddToBlockCache() { var peer = _peerPool.GetPeers(true).First(); var pubkey = peer.Info.Pubkey; var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; Hash hash = Hash.FromRawBytes(new byte[] { 3, 6, 9 }); var announcement = new BlockAnnouncement { BlockHeight = 1, BlockHash = hash }; await _serverService.SendAnnouncement(announcement, BuildServerCallContext(metadata)); peer.TryAddKnownBlock(hash).ShouldBeFalse(); }
public void AddKnowBlock(BlockAnnouncement blockAnnouncement) { if (blockAnnouncement.HasFork) { _recentBlockHeightAndHashMappings.Clear(); return; } CurrentBlockHeight = blockAnnouncement.BlockHeight; CurrentBlockHash = blockAnnouncement.BlockHash; _recentBlockHeightAndHashMappings[CurrentBlockHeight] = CurrentBlockHash; while (_recentBlockHeightAndHashMappings.Count > 10) { _recentBlockHeightAndHashMappings.TryRemove(_recentBlockHeightAndHashMappings.Keys.Min(), out _); } }
public async Task ValidateAnnouncement_Success() { var chain = await _blockchainService.GetChainAsync(); var blockAnnouncement = new BlockAnnouncement { BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), BlockHeight = chain.LastIrreversibleBlockHeight + 1 }; var validateResult = await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, GetEncodedPubKeyString()); validateResult.ShouldBeTrue(); }
private async Task ProcessNewBlockAsync(BlockAnnouncement blockAnnouncement, string senderPubkey) { var chain = await _blockchainService.GetChainAsync(); if (!await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, senderPubkey)) { return; } await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { SyncBlockHash = blockAnnouncement.BlockHash, SyncBlockHeight = blockAnnouncement.BlockHeight, SuggestedPeerPubkey = senderPubkey, BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount }); }
public Task BroadcastAnnounceAsync(BlockHeader blockHeader) { var blockHash = blockHeader.GetHash(); if (IsOldBlock(blockHeader)) { return(Task.CompletedTask); } var blockAnnouncement = new BlockAnnouncement { BlockHash = blockHash, BlockHeight = blockHeader.Height }; foreach (var peer in _peerPool.GetPeers()) { try { if (peer.KnowsBlock(blockHash)) { continue; // block already known to this peer } peer.EnqueueAnnouncement(blockAnnouncement, async ex => { peer.TryAddKnownBlock(blockHash); if (ex != null) { Logger.LogInformation(ex, $"Could not broadcast announcement to {peer} " + $"- status {peer.ConnectionStatus}."); await HandleNetworkException(peer, ex); } }); } catch (NetworkException ex) { Logger.LogWarning(ex, $"Could not enqueue announcement to {peer} " + $"- status {peer.ConnectionStatus}."); } } return(Task.CompletedTask); }
public Task ProcessAnnouncement(BlockAnnouncement announcement, ServerCallContext context) { if (announcement?.BlockHash == null) { Logger.LogError($"Received null announcement or header from {context.GetPeerInfo()}."); return(Task.CompletedTask); } Logger.LogDebug($"Received announce {announcement.BlockHash} from {context.GetPeerInfo()}."); var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey()); peer?.AddKnowBlock(announcement); _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, context.GetPublicKey())); return(Task.CompletedTask); }
public Task BroadcastAnnounceAsync(BlockHeader blockHeader, bool hasFork) { var blockHash = blockHeader.GetHash(); if (IsOldBlock(blockHeader)) { return(Task.CompletedTask); } var blockAnnouncement = new BlockAnnouncement { BlockHash = blockHash, BlockHeight = blockHeader.Height, HasFork = hasFork }; foreach (var peer in _peerPool.GetPeers()) { try { if (peer.KnowsBlock(blockHash)) { return(Task.CompletedTask); // block already known to this peer } peer.EnqueueAnnouncement(blockAnnouncement, async ex => { peer.TryAddKnownBlock(blockHash); if (ex != null) { Logger.LogError(ex, $"Error while broadcasting announcement to {peer}."); await HandleNetworkException(peer, ex); } }); } catch (NetworkException ex) { Logger.LogError(ex, $"Error while broadcasting announcement to {peer}."); } } return(Task.CompletedTask); }
private async Task ProcessNewBlockAsync(BlockAnnouncement blockAnnouncement, string senderPubkey) { Logger.LogDebug( $"Start block sync job, target height: {blockAnnouncement.BlockHeight}, target block hash: {blockAnnouncement.BlockHash}, peer: {senderPubkey}"); var chain = await _blockchainService.GetChainAsync(); if (!await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, senderPubkey)) { return; } await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { SyncBlockHash = blockAnnouncement.BlockHash, SyncBlockHeight = blockAnnouncement.BlockHeight, SuggestedPeerPubkey = senderPubkey, BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount }); }
public async Task AnnounceAsync_Success() { AnnouncementReceivedEventData received = null; _eventBus.Subscribe <AnnouncementReceivedEventData>(a => { received = a; return(Task.CompletedTask); }); var header = new BlockAnnouncement { BlockHeight = 100, BlockHash = Hash.FromRawBytes(new byte[] { 9, 2 }) }; await _grpcPeer.SendAnnouncementAsync(header); received.ShouldNotBeNull(); received.Announce.BlockHeight.ShouldBe(100); }
/// <summary> /// Send a announcement to the peer using the stream call. /// Note: this method is not thread safe. /// </summary> private async Task SendAnnouncementAsync(BlockAnnouncement header) { if (_announcementStreamCall == null) { _announcementStreamCall = _client.AnnouncementBroadcastStream(new Metadata { { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }); } try { await _announcementStreamCall.RequestStream.WriteAsync(header); } catch (RpcException) { _announcementStreamCall.Dispose(); _announcementStreamCall = null; throw; } }
public async Task ValidateAnnouncement_AlreadySynchronized() { var chain = await _blockchainService.GetChainAsync(); var blockAnnouncement = new BlockAnnouncement { BlockHash = Hash.FromString("SyncBlockHash"), BlockHeight = chain.LastIrreversibleBlockHeight + 1 }; var validateResult = await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, GetEncodedPubKeyString()); validateResult.ShouldBeTrue(); validateResult = await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, GetEncodedPubKeyString()); validateResult.ShouldBeFalse(); }
/// <summary> /// Send a announcement to the peer using the stream call. /// Note: this method is not thread safe. /// </summary> public async Task SendAnnouncementAsync(BlockAnnouncement header) { if (!IsConnected) { return; } if (_announcementStreamCall == null) { _announcementStreamCall = _client.AnnouncementBroadcastStream(); } try { await _announcementStreamCall.RequestStream.WriteAsync(header); } catch (RpcException e) { _announcementStreamCall.Dispose(); _announcementStreamCall = null; HandleFailure(e, $"Error during announcement broadcast: {header.BlockHash}."); } }
private Task ProcessAnnouncementAsync(BlockAnnouncement announcement, string peerPubkey) { if (announcement?.BlockHash == null) { Logger.LogWarning($"Received null announcement or header from {peerPubkey}."); return(Task.CompletedTask); } var peer = TryGetPeerByPubkey(peerPubkey); if (!peer.TryAddKnownBlock(announcement.BlockHash)) { return(Task.CompletedTask); } if (peer.SyncState != SyncState.Finished) { peer.SyncState = SyncState.Finished; } _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, peerPubkey)); return(Task.CompletedTask); }
/// <summary> /// This method is called when a peer wants to broadcast an announcement. /// </summary> public override async Task <VoidReply> SendAnnouncement(BlockAnnouncement an, ServerCallContext context) { await ProcessAnnouncement(an, context); return(new VoidReply()); }
public AnnouncementReceivedEventData(BlockAnnouncement an, string senderPubKey) { SenderPubKey = senderPubKey; Announce = an; }