/// <summary>
        /// Processing pipeline for a block contains ValidateBlockBeforeExecute, ExecuteBlock and ValidateBlockAfterExecute.
        /// </summary>
        /// <param name="block"></param>
        /// <returns>Block processing result is true if succeed, otherwise false.</returns>
        private async Task <bool> TryProcessBlockAsync(Block block)
        {
            var blockHash = block.GetHash();

            // Set the other blocks as bad block if found the first bad block
            if (!await _blockValidationService.ValidateBlockBeforeExecuteAsync(block))
            {
                Logger.LogWarning($"Block validate fails before execution. block hash : {blockHash}");
                return(false);
            }

            if (!await TryExecuteBlockAsync(block))
            {
                Logger.LogWarning($"Block execution failed. block hash : {blockHash}");
                return(false);
            }

            if (!await _blockValidationService.ValidateBlockAfterExecuteAsync(block))
            {
                Logger.LogWarning($"Block validate fails after execution. block hash : {blockHash}");
                return(false);
            }

            await _transactionResultService.ProcessTransactionResultAfterExecutionAsync(block.Header,
                                                                                        block.Body.TransactionIds.ToList());

            return(true);
        }
        /// <summary>
        /// Processing pipeline for a block contains ValidateBlockBeforeExecute, ExecuteBlock and ValidateBlockAfterExecute.
        /// </summary>
        /// <param name="block"></param>
        /// <returns>Block processing result is true if succeed, otherwise false.</returns>
        private async Task <BlockExecutedSet> ProcessBlockAsync(Block block)
        {
            var blockHash = block.GetHash();

            // Set the other blocks as bad block if found the first bad block
            if (!await _blockValidationService.ValidateBlockBeforeExecuteAsync(block))
            {
                Logger.LogDebug($"Block validate fails before execution. block hash : {blockHash}");
                return(null);
            }

            var blockExecutedSet = await ExecuteBlockAsync(block);

            if (blockExecutedSet == null)
            {
                Logger.LogDebug($"Block execution failed. block hash : {blockHash}");
                return(null);
            }

            if (!await _blockValidationService.ValidateBlockAfterExecuteAsync(block))
            {
                Logger.LogDebug($"Block validate fails after execution. block hash : {blockHash}");
                return(null);
            }

            await _transactionResultService.ProcessTransactionResultAfterExecutionAsync(block.Header,
                                                                                        block.Body.TransactionIds.ToList());

            return(blockExecutedSet);
        }
Example #3
0
        public async Task <List <ChainBlockLink> > ExecuteBlocksAttachedToLongestChain(Chain chain, BlockAttachOperationStatus status)
        {
            if (!status.HasFlag(BlockAttachOperationStatus.LongestChainFound))
            {
                Logger.LogTrace($"Try to attach to chain but the status is {status}.");
                return(null);
            }

            var successLinks = new List <ChainBlockLink>();
            var blockLinks   = await _chainManager.GetNotExecutedBlocks(chain.LongestChainHash);

            try
            {
                foreach (var blockLink in blockLinks)
                {
                    var linkedBlock = await _blockchainService.GetBlockByHashAsync(blockLink.BlockHash);

                    // Set the other blocks as bad block if found the first bad block
                    if (!await _blockValidationService.ValidateBlockBeforeExecuteAsync(linkedBlock))
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionFailed);

                        Logger.LogWarning($"Block validate fails before execution. block hash : {blockLink.BlockHash}");
                        break;
                    }

                    if (!await ExecuteBlock(blockLink, linkedBlock))
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionFailed);

                        Logger.LogWarning($"Block execution failed. block hash : {blockLink.BlockHash}");
                        break;
                    }

                    if (!await _blockValidationService.ValidateBlockAfterExecuteAsync(linkedBlock))
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionFailed);

                        Logger.LogWarning($"Block validate fails after execution. block hash : {blockLink.BlockHash}");
                        break;
                    }

                    await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionSuccess);

                    successLinks.Add(blockLink);

                    Logger.LogInformation($"Executed block {blockLink.BlockHash} at height {blockLink.Height}.");

                    await LocalEventBus.PublishAsync(new BlockAcceptedEvent()
                    {
                        BlockHeader = linkedBlock.Header
                    });
                }
            }
            catch (ValidateNextTimeBlockValidationException ex)
            {
                Logger.LogWarning($"Block validate fails after execution. Exception message {ex.Message}");
            }

            if (successLinks.Count > 0)
            {
                var blockLink = successLinks.Last();
                await _blockchainService.SetBestChainAsync(chain, blockLink.Height, blockLink.BlockHash);

                await LocalEventBus.PublishAsync(new BestChainFoundEventData
                {
                    BlockHash      = chain.BestChainHash,
                    BlockHeight    = chain.BestChainHeight,
                    ExecutedBlocks = successLinks.Select(p => p.BlockHash).ToList()
                });
            }

            Logger.LogInformation($"Attach blocks to best chain, status: {status}, best chain hash: {chain.BestChainHash}, height: {chain.BestChainHeight}");

            return(blockLinks);
        }