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 successBlocks = new List <Block>();
            var blockLinks    = await _chainManager.GetNotExecutedBlocks(chain.LongestChainHash);

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

                    var processResult = await TryProcessBlockAsync(linkedBlock);

                    if (!processResult)
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatusAsync(blockLink,
                                                                                  ChainBlockLinkExecutionStatus.ExecutionFailed);

                        await _chainManager.RemoveLongestBranchAsync(chain);

                        return(null);
                    }

                    successLinks.Add(blockLink);
                    successBlocks.Add(linkedBlock);
                    Logger.LogInformation(
                        $"Executed block {blockLink.BlockHash} at height {blockLink.Height}, with {linkedBlock.Body.TransactionsCount} txns.");

                    await LocalEventBus.PublishAsync(new BlockAcceptedEvent { Block = linkedBlock });
                }
            }
            catch (BlockValidationException ex)
            {
                if (!(ex.InnerException is ValidateNextTimeBlockValidationException))
                {
                    await _chainManager.RemoveLongestBranchAsync(chain);

                    throw;
                }

                Logger.LogWarning(
                    $"Block validation failed: {ex.Message}. Inner exception {ex.InnerException.Message}");
            }
            catch (Exception ex)
            {
                await _chainManager.RemoveLongestBranchAsync(chain);

                Logger.LogWarning($"Block validate or execute fails. Exception message {ex.Message}");
                throw;
            }

            if (successLinks.Count == 0 || successLinks.Last().Height < chain.BestChainHeight)
            {
                Logger.LogWarning("No block execution succeed or no block is higher than best chain.");
                await _chainManager.RemoveLongestBranchAsync(chain);

                return(null);
            }

            await SetBestChainAsync(successLinks, chain);

            await _chainManager.SetChainBlockLinkExecutionStatusesAsync(successLinks,
                                                                        ChainBlockLinkExecutionStatus.ExecutionSuccess);

            await PublishBestChainFoundEventAsync(chain, successBlocks);

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

            return(blockLinks);
        }
Ejemplo n.º 2
0
 public async Task RemoveLongestBranchAsync(Chain chain)
 {
     await _chainManager.RemoveLongestBranchAsync(chain);
 }