/// <summary> /// Mock a chain with a best branch, and some fork branches /// </summary> /// <returns> /// Mock Chain /// BestChainHeight: 11 /// LongestChainHeight: 13 /// LIB height: 5 /// /// Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> 18 -> 19 /// Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k /// Longest Branch: (h)-> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v /// Fork Branch: (e)-> q -> r -> s -> t -> u /// Unlinked Branch: v -> w -> x -> y -> z /// </returns> public async Task <Chain> MockChainAsync() { var chain = await CreateChain(); var genesisBlock = await _blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); BestBranchBlockList.Add(genesisBlock); BestBranchBlockList.AddRange(await AddBestBranch()); LongestBranchBlockList = await AddForkBranch(BestBranchBlockList[7].Height, BestBranchBlockList[7].GetHash(), 11); foreach (var block in LongestBranchBlockList) { var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, ChainBlockLinkExecutionStatus.ExecutionFailed); } ForkBranchBlockList = await AddForkBranch(BestBranchBlockList[4].Height, BestBranchBlockList[4].GetHash()); UnlinkedBranchBlockList = await AddForkBranch(9, Hash.FromString("UnlinkBlock")); // Set lib chain = await _blockchainService.GetChainAsync(); await _blockchainService.SetIrreversibleBlockAsync(chain, BestBranchBlockList[4].Height, BestBranchBlockList[4].GetHash()); return(chain); }
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); }
public async Task SetChainBlockLinkExecutionStatusAsync(Hash blockHash, ChainBlockLinkExecutionStatus status) { var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(blockHash); await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, status); }