public async Task MergeBlockStateAsync(ChainStateInfo chainStateInfo, Hash blockStateHash)
        {
            var blockState = await _blockStateSets.GetAsync(blockStateHash.ToStorageKey());

            if (blockState == null)
            {
                if (chainStateInfo.Status == ChainStateMergingStatus.Merged &&
                    chainStateInfo.MergingBlockHash == blockStateHash)
                {
                    chainStateInfo.Status           = ChainStateMergingStatus.Common;
                    chainStateInfo.MergingBlockHash = null;

                    await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo);

                    return;
                }

                throw new InvalidOperationException($"cannot get block state of {blockStateHash}");
            }

            if (chainStateInfo.BlockHash == null || chainStateInfo.BlockHash == blockState.PreviousHash ||
                (chainStateInfo.Status == ChainStateMergingStatus.Merged &&
                 chainStateInfo.MergingBlockHash == blockState.BlockHash))
            {
                chainStateInfo.Status           = ChainStateMergingStatus.Merging;
                chainStateInfo.MergingBlockHash = blockStateHash;

                await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo);

                var dic = blockState.Changes.Select(change => new VersionedState()
                {
                    Key         = change.Key,
                    Value       = change.Value,
                    BlockHash   = blockState.BlockHash,
                    BlockHeight = blockState.BlockHeight,
                    //OriginBlockHash = origin.BlockHash
                }).ToDictionary(p => p.Key, p => p);

                await _versionedStates.SetAllAsync(dic);

                await _versionedStates.RemoveAllAsync(blockState.Deletes.ToList());

                chainStateInfo.Status      = ChainStateMergingStatus.Merged;
                chainStateInfo.BlockHash   = blockState.BlockHash;
                chainStateInfo.BlockHeight = blockState.BlockHeight;
                await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo);

                await _blockStateSets.RemoveAsync(blockStateHash.ToStorageKey());

                chainStateInfo.Status           = ChainStateMergingStatus.Common;
                chainStateInfo.MergingBlockHash = null;

                await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo);
            }
            else
            {
                throw new InvalidOperationException(
                          "cannot merge block not linked, check new block's previous block hash ");
            }
        }
        public async Task GlobalSetup()
        {
            _chains = GetRequiredService <IBlockchainStore <Chain> >();
            _chainStateInfoCollection = GetRequiredService <IStateStore <ChainStateInfo> >();
            _blockchainStateService   = GetRequiredService <IBlockchainStateService>();
            _blockStateSetManger      = GetRequiredService <IBlockStateSetManger>();
            _blockchainService        = GetRequiredService <IBlockchainService>();
            _osTestHelper             = GetRequiredService <OSTestHelper>();
            _chainManager             = GetRequiredService <IChainManager>();
            _blockManager             = GetRequiredService <IBlockManager>();
            _transactionManager       = GetRequiredService <ITransactionManager>();
            _transactionPoolService   = GetRequiredService <ITransactionPoolService>();


            _blockStateSets = new List <BlockStateSet>();
            _blocks         = new List <Block>();

            _chain = await _blockchainService.GetChainAsync();

            var blockHash = _chain.BestChainHash;

            while (true)
            {
                var blockState = await _blockStateSetManger.GetBlockStateSetAsync(blockHash);

                _blockStateSets.Add(blockState);

                var blockHeader = await _blockchainService.GetBlockHeaderByHashAsync(blockHash);

                blockHash = blockHeader.PreviousBlockHash;
                if (blockHash == _chain.LastIrreversibleBlockHash)
                {
                    break;
                }
            }

            await _blockchainStateService.MergeBlockStateAsync(_chain.BestChainHeight, _chain.BestChainHash);

            for (var i = 0; i < BlockCount; i++)
            {
                var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount);

                await _osTestHelper.BroadcastTransactions(transactions);

                var block = await _osTestHelper.MinedOneBlock();

                _blocks.Add(block);

                var blockState = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash());

                _blockStateSets.Add(blockState);
            }

            var chain = await _blockchainService.GetChainAsync();

            await _chainManager.SetIrreversibleBlockAsync(chain, chain.BestChainHash);

            _chainStateInfo = await _chainStateInfoCollection.GetAsync(chain.Id.ToStorageKey());
        }
        public async Task MergeBlockState_ShouldThrowInvalidOperationException()
        {
            var chainStateInfo = new ChainStateInfo
            {
                BlockHash        = _tv[1].BlockHash,
                BlockHeight      = _tv[1].BlockHeight,
                MergingBlockHash = null,
                Status           = ChainStateMergingStatus.Common
            };

            await Assert.ThrowsAsync <InvalidOperationException>(async() =>
                                                                 await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash));
        }
示例#4
0
        public async Task MergeBlockState_WithStatus_Merging()
        {
            await _blockchainStateManager.SetBlockStateSetAsync(new BlockStateSet()
            {
                BlockHash    = _tv[0].BlockHash,
                BlockHeight  = _tv[0].BlockHeight,
                PreviousHash = Hash.FromString("PreviousHash"),
                Changes      =
                {
                    {
                        _tv[1].Key,
                        _tv[1].Value
                    }
                }
            });

            await _blockchainStateManager.SetBlockStateSetAsync(new BlockStateSet()
            {
                BlockHash    = _tv[1].BlockHash,
                BlockHeight  = _tv[1].BlockHeight,
                PreviousHash = _tv[0].BlockHash,
                Changes      =
                {
                    {
                        _tv[1].Key,
                        _tv[1].Value
                    }
                }
            });

            var chainStateInfo = new ChainStateInfo
            {
                BlockHash        = _tv[0].BlockHash,
                BlockHeight      = _tv[0].BlockHeight,
                MergingBlockHash = _tv[1].BlockHash,
                Status           = ChainStateMergingStatus.Merging
            };

            await _blockchainStateManager.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash);

            chainStateInfo = await _blockchainStateManager.GetChainStateInfoAsync();

            chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash);
            chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight);
            chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common);
            chainStateInfo.MergingBlockHash.ShouldBeNull();

            var blockStateSet = await _blockchainStateManager.GetBlockStateSetAsync(_tv[1].BlockHash);

            blockStateSet.ShouldBeNull();
        }
示例#5
0
        public async Task MergeBlockState_WithStatus_Merged_WithSet_Removed()
        {
            var chainStateInfo = new ChainStateInfo
            {
                BlockHash        = _tv[1].BlockHash,
                BlockHeight      = _tv[1].BlockHeight,
                MergingBlockHash = _tv[1].BlockHash,
                Status           = ChainStateMergingStatus.Merged
            };

            await _blockchainStateManager.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash);

            chainStateInfo = await _blockchainStateManager.GetChainStateInfoAsync();

            chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash);
            chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight);
            chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common);
            chainStateInfo.MergingBlockHash.ShouldBeNull();
        }