示例#1
0
        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>();
        }
示例#2
0
        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);
        }
示例#4
0
        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);
        }
示例#7
0
 public void SetChainBlockLink(ChainBlockLink chainBlockLink)
 {
     _cachedChainBlockLinks[chainBlockLink.BlockHash] = chainBlockLink;
 }
示例#8
0
        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);
        }