public Task <ByteString> GetStateAsync(Address contractAddress, string key, long blockHeight, Hash blockHash) { var address = contractAddress.GetFormatted(); if (!key.StartsWith(address)) { throw new InvalidOperationException("a contract cannot access other contracts data"); } return(_blockchainStateManager.GetStateAsync(key, blockHeight, blockHash)); }
public async Task AddBlockStateSet_Test() { // one level tests without best chain state await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() { BlockHash = _tv[1].BlockHash, BlockHeight = _tv[1].BlockHeight, PreviousHash = null, Changes = { { _tv[1].Key, _tv[1].Value }, { _tv[2].Key, _tv[2].Value }, } }); var check1 = new Func <Task>(async() => { (await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[1].BlockHeight, _tv[1].BlockHash)) .ShouldBe(_tv[1].Value); (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[1].BlockHeight, _tv[1].BlockHash)) .ShouldBe(_tv[2].Value); }); await check1(); //two level tests without best chain state await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() { BlockHash = _tv[2].BlockHash, BlockHeight = _tv[2].BlockHeight, PreviousHash = _tv[1].BlockHash, Changes = { //override key 1 { _tv[1].Key, _tv[2].Value }, } }); var check2 = new Func <Task>(async() => { //key 1 was changed, value was changed to value 2 (await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[2].BlockHeight, _tv[2].BlockHash)) .ShouldBe(_tv[2].Value); (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[2].BlockHeight, _tv[2].BlockHash)) .ShouldBe(_tv[2].Value); }); await check2(); //but when we we can get value at the height of block height 1, also block hash 1 await check1(); await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() { BlockHash = _tv[3].BlockHash, BlockHeight = _tv[3].BlockHeight, PreviousHash = _tv[2].BlockHash, Changes = { //override key 2 at height 3 { _tv[2].Key, _tv[4].Value }, } }); var check3_1 = new Func <Task>(async() => { (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[3].BlockHeight, _tv[3].BlockHash)) .ShouldBe(_tv[4].Value); }); await check1(); await check2(); await check3_1(); await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() { BlockHash = _tv[4].BlockHash, BlockHeight = _tv[3].BlockHeight, // it's a branch PreviousHash = _tv[2].BlockHash, Changes = { //override key 2 at height 3 { _tv[2].Key, _tv[5].Value }, } }); var check3_2 = new Func <Task>(async() => { (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[3].BlockHeight, _tv[4].BlockHash)) .ShouldBe(_tv[5].Value); }); await check1(); await check2(); await check3_2(); var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); await check1(); await check2(); await check3_1(); await check3_2(); await Assert.ThrowsAsync <InvalidOperationException>(async() => await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[3].BlockHash)); await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash); await Assert.ThrowsAsync <InvalidOperationException>(async() => await check1()); await check2(); //test failed merge recover chainStateInfo.Status = ChainStateMergingStatus.Merging; chainStateInfo.MergingBlockHash = _tv[4].BlockHash; //merge best to second branch await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[4].BlockHash); await Assert.ThrowsAsync <InvalidOperationException>(async() => await check1()); await Assert.ThrowsAsync <InvalidOperationException>(async() => await check2()); await Assert.ThrowsAsync <InvalidOperationException>(async() => await check3_1()); await check3_2(); //test failed merge recover chainStateInfo.Status = ChainStateMergingStatus.Merged; chainStateInfo.MergingBlockHash = _tv[4].BlockHash; await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[4].BlockHash); }