/// <summary> /// The entrance of block syncing. /// First step is to validate block header of this block. /// </summary> /// <param name="block"></param> /// <returns></returns> public async Task ReceiveBlock(IBlock block) { if (_terminated) { return; } var isReceiveBlock = await IsReceiveBlock(block); if (!isReceiveBlock) { return; } if (!_blockSet.IsBlockReceived(block.GetHash(), block.Index)) { _blockSet.AddBlock(block); // Notify the network layer the block has been accepted. MessageHub.Instance.Publish(new BlockAccepted(block)); } if (CurrentState != NodeState.Catching && CurrentState != NodeState.Caught) { return; } var blockHeaderValidationResult = await _blockHeaderValidator.ValidateBlockHeaderAsync(block.Header); _logger?.Trace( $"BlockHeader validation result: {blockHeaderValidationResult.ToString()} - {block.BlockHashToHex}. Height: *{block.Index}*"); if (blockHeaderValidationResult == BlockHeaderValidationResult.Success) { // Catching -> BlockValidating // Caught -> BlockValidating MessageHub.Instance.Publish(StateEvent.ValidBlockHeader); await HandleBlock(block); } if (blockHeaderValidationResult == BlockHeaderValidationResult.Unlinkable) { MessageHub.Instance.Publish(new UnlinkableHeader(block.Header)); } if (blockHeaderValidationResult == BlockHeaderValidationResult.MaybeForked) { MessageHub.Instance.Publish(StateEvent.LongerChainDetected); } if (blockHeaderValidationResult == BlockHeaderValidationResult.Branched) { MessageHub.Instance.Publish(new LockMining(false)); } if (await IsRequestNextBlockAgain(block)) { MessageHub.Instance.Publish(new BlockAccepted(block)); } }