public async Task Test_Set_Block_Executed() { var firstBlockLink = new ChainBlockLink { Height = 1.BlockHeight(), BlockHash = _blocks[1], ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone }; await _chainManager.SetChainBlockLinkExecutionStatus(firstBlockLink, ChainBlockLinkExecutionStatus.ExecutionSuccess); var currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[1]); currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); var secondBlockLink = new ChainBlockLink { Height = 2.BlockHeight(), BlockHash = _blocks[2], ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionSuccess }; _chainManager .SetChainBlockLinkExecutionStatus(secondBlockLink, ChainBlockLinkExecutionStatus.ExecutionSuccess) .ShouldThrow <InvalidOperationException>(); }
public async Task <BlockAttachOperationStatus> AttachBlockToChainAsync(Chain chain, Block block) { var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); if (chainBlockLink == null) { chainBlockLink = new ChainBlockLink { Height = block.Header.Height, BlockHash = block.GetHash(), PreviousBlockHash = block.Header.PreviousBlockHash }; } else { chainBlockLink.IsLinked = false; chainBlockLink.ExecutionStatus = chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionSuccess ? ChainBlockLinkExecutionStatus.ExecutionSuccess : ChainBlockLinkExecutionStatus.ExecutionNone; } var status = await _chainManager.AttachBlockToChainAsync(chain, chainBlockLink); return(status); }
public async Task SetChainBlockLinkExecutionStatusAsync(ChainBlockLink blockLink, ChainBlockLinkExecutionStatus status) { if (blockLink.ExecutionStatus != ChainBlockLinkExecutionStatus.ExecutionNone || status == ChainBlockLinkExecutionStatus.ExecutionNone) { throw new InvalidOperationException(); } blockLink.ExecutionStatus = status; await SetChainBlockLinkAsync(blockLink); }
private async Task <bool> ExecuteBlock(ChainBlockLink blockLink, Block block) { var blockState = await _blockchainStateManager.GetBlockStateSetAsync(block.GetHash()); if (blockState != null) { return(true); } var blockHash = block.GetHash(); var executedBlock = await _blockExecutingService.ExecuteBlockAsync(block.Header, block.Body.TransactionList); return(executedBlock.GetHash().Equals(blockHash)); }
public async Task <BlockAttachOperationStatus> AttachBlockToChainAsync(Chain chain, ChainBlockLink chainBlockLink) { BlockAttachOperationStatus status = BlockAttachOperationStatus.None; bool isLinkedToLongestChain = chainBlockLink.PreviousBlockHash == chain.LongestChainHash && chainBlockLink.Height == chain.LongestChainHeight + 1; Logger.LogDebug( $"Start attach block hash {chainBlockLink.BlockHash}, height {chainBlockLink.Height}"); while (true) { var previousHash = chainBlockLink.PreviousBlockHash.ToStorageKey(); var blockHash = chainBlockLink.BlockHash.ToStorageKey(); if (chain.Branches.ContainsKey(previousHash)) { chain.Branches[blockHash] = chainBlockLink.Height; chain.Branches.Remove(previousHash); if (isLinkedToLongestChain && chainBlockLink.Height > chain.LongestChainHeight || chainBlockLink.Height >= chain.LongestChainHeight + 8) { chain.LongestChainHeight = chainBlockLink.Height; chain.LongestChainHash = chainBlockLink.BlockHash; status |= BlockAttachOperationStatus.LongestChainFound; } if (chainBlockLink.IsLinked) { throw new Exception("chain block link should not be linked"); } chainBlockLink.IsLinked = true; await SetChainBlockLinkAsync(chainBlockLink); if (!chain.NotLinkedBlocks.ContainsKey(blockHash)) { status |= BlockAttachOperationStatus.NewBlockLinked; break; } chainBlockLink = await GetChainBlockLinkWithCacheAsync(chain.NotLinkedBlocks[blockHash]); chain.NotLinkedBlocks.Remove(blockHash); status |= BlockAttachOperationStatus.NewBlocksLinked; } else { //check database to ensure whether it can be a branch var previousChainBlockLink = await this.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); if (previousChainBlockLink != null && previousChainBlockLink.IsLinked) { chain.Branches[previousChainBlockLink.BlockHash.ToStorageKey()] = previousChainBlockLink.Height; continue; } chain.NotLinkedBlocks[previousHash] = blockHash; if (status != BlockAttachOperationStatus.None) { throw new Exception("invalid status"); } status = BlockAttachOperationStatus.NewBlockNotLinked; await SetChainBlockLinkAsync(chainBlockLink); break; } } await _chains.SetAsync(chain.Id.ToStorageKey(), chain); Logger.LogInformation($"Attach {chainBlockLink.BlockHash} to longest chain, status: {status}, " + $"longest chain height: {chain.LongestChainHeight}, longest chain hash: {chain.LongestChainHash}"); return(status); }
public async Task SetChainBlockLinkAsync(ChainBlockLink chainBlockLink) { await _chainBlockLinks.SetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + chainBlockLink.BlockHash.ToStorageKey(), chainBlockLink); _chainBlockLinkCacheProvider.SetChainBlockLink(chainBlockLink); }
public void SetChainBlockLink(ChainBlockLink chainBlockLink) { _cachedChainBlockLinks[chainBlockLink.BlockHash] = chainBlockLink; }
public async Task <List <Hash> > GetBlockHashesAsync(Chain chain, Hash firstHash, int count, Hash chainBranchBlockHash) { var first = await _blockManager.GetBlockHeaderAsync(firstHash); if (first == null) { return(new List <Hash>()); } var height = first.Height + count; var chainBranchBlockHashKey = chainBranchBlockHash.ToStorageKey(); ChainBlockLink chainBlockLink = null; if (chain.Branches.ContainsKey(chainBranchBlockHashKey)) { if (height > chain.Branches[chainBranchBlockHashKey]) { height = chain.Branches[chainBranchBlockHashKey]; count = (int)(height - first.Height); } } else { var branchChainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); if (height > branchChainBlockLink.Height) { height = branchChainBlockLink.Height; chainBlockLink = branchChainBlockLink; count = (int)(height - first.Height); } } var hashes = new List <Hash>(); if (count <= 0) { return(hashes); } if (chainBlockLink == null) { var last = await GetBlockHashByHeightAsync(chain, height, chainBranchBlockHash); if (last == null) { throw new InvalidOperationException("not support"); } chainBlockLink = await _chainManager.GetChainBlockLinkAsync(last); } hashes.Add(chainBlockLink.BlockHash); for (var i = 0; i < count - 1; i++) { chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); hashes.Add(chainBlockLink.BlockHash); } if (chainBlockLink.PreviousBlockHash != firstHash) { throw new Exception("wrong branch"); } hashes.Reverse(); return(hashes); }