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)); }
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(); }
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(); }