Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn BlockChain.GetStates() into GetState() #563

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ To be released.
disposed to clean up its internal resources. [[#485]]
- `IStore.IterateStateReferences()` method became to receive
`highestIndex`, `lowestIndex`, and `limit` parameters. [[#447], [#545]]
- Reworked `BlockChain<T>.GetStates()` into `GetState()` which takes only one `Address` instead of `IEnumerable<Address>`. [[#510], [#563]]

### Added interfaces

Expand All @@ -35,12 +36,14 @@ To be released.
[#447]: https://github.com/planetarium/libplanet/issues/447
[#462]: https://github.com/planetarium/libplanet/issues/462
[#485]: https://github.com/planetarium/libplanet/pull/485
[#510]: https://github.com/planetarium/libplanet/issues/510
[#545]: https://github.com/planetarium/libplanet/pull/545
[#550]: https://github.com/planetarium/libplanet/issues/550
[#555]: https://github.com/planetarium/libplanet/issues/555
[#558]: https://github.com/planetarium/libplanet/pull/558
[#560]: https://github.com/planetarium/libplanet/pull/560
[#562]: https://github.com/planetarium/libplanet/pull/562
[#563]: https://github.com/planetarium/libplanet/pull/563


Version 0.6.0
Expand Down
103 changes: 53 additions & 50 deletions Libplanet.Tests/Blockchain/BlockChainTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public async void ProcessActions()
);
await chain.MineBlock(_fx.Address1);

AddressStateMap states = chain.GetStates(new[] { _fx.Address1 });
AddressStateMap states = chain.GetState(_fx.Address1);
Assert.NotEmpty(states);

var result = (BattleResult)states[_fx.Address1];
Expand Down Expand Up @@ -263,7 +263,7 @@ public async void ProcessActions()
);
await chain.MineBlock(_fx.Address1);

states = chain.GetStates(new List<Address> { _fx.Address1 });
states = chain.GetState(_fx.Address1);
result = (BattleResult)states[_fx.Address1];
Assert.Contains("bow", result.UsedWeapons);

Expand All @@ -284,7 +284,7 @@ public async void ProcessActions()
ImmutableHashSet<Transaction<PolymorphicAction<BaseAction>>>.Empty.Add(tx3)
);
await chain.MineBlock(_fx.Address1);
states = chain.GetStates(new List<Address> { _fx.Address1 });
states = chain.GetState(_fx.Address1);

Assert.NotEmpty(states);
}
Expand Down Expand Up @@ -359,7 +359,7 @@ public void Append()
var minerAddress = addresses[4];
var blockRenders = MinerReward.RenderRecords.Value;

Assert.Equal(2, _blockChain.GetStates(new[] { minerAddress })[minerAddress]);
Assert.Equal(2, _blockChain.GetState(minerAddress)[minerAddress]);
Assert.Equal(2, blockRenders.Count);
Assert.True(blockRenders.All(r => r.Render));
Assert.Equal(0, blockRenders[0].Context.BlockIndex);
Expand Down Expand Up @@ -884,7 +884,7 @@ public void Swap(bool render)

Assert.Equal(
totalBlockCount,
_blockChain.GetStates(new[] { minerAddress })[minerAddress]);
_blockChain.GetState(minerAddress)[minerAddress]);
Assert.Equal(totalBlockCount, blockRenders.Count);
Assert.True(blockRenders.Take(unRenderBlockCount).All(r => r.Unrender));
Assert.True(blockRenders.Skip(unRenderBlockCount).All(r => r.Render));
Expand All @@ -904,7 +904,7 @@ public void Swap(bool render)
// This is a regression test for:
// https://github.com/planetarium/libplanet/issues/189#issuecomment-482443607.
[Fact]
public void GetStatesOnlyDrillsDownUntilRequestedAddressesAreFound()
public void GetStateOnlyDrillsDownUntilRequestedAddressesAreFound()
{
var tracker = new StoreTracker(_fx.Store);
var chain = new BlockChain<DumbAction>(
Expand Down Expand Up @@ -939,14 +939,15 @@ public void GetStatesOnlyDrillsDownUntilRequestedAddressesAreFound()
testingDepth,
Math.Min(10, addresses.Length - testingDepth - 1)
).Select(i => addresses[i]).ToArray();
AddressStateMap result = chain.GetStates(targetAddresses);
string resultString = string.Join(", ", result.Keys);
string targetString = string.Join(", ", targetAddresses);
string message =
$"The result dictionary ({resultString}) does not " +
$"cover all requested addresses ({targetString}).";

foreach (Address targetAddress in targetAddresses)
{
AddressStateMap result = chain.GetState(targetAddress);

string message =
$"The result dictionary ({result.Keys}) does not " +
$"cover the requested address ({targetAddress}).";

Assert.True(result.ContainsKey(targetAddress), message);
}

Expand All @@ -957,7 +958,7 @@ public void GetStatesOnlyDrillsDownUntilRequestedAddressesAreFound()
}

[Fact]
public void GetStatesReturnsEarlyForNonexistentAccount()
public void GetStateReturnsEarlyForNonexistentAccount()
{
var tracker = new StoreTracker(_fx.Store);
var chain = new BlockChain<DumbAction>(
Expand All @@ -975,7 +976,7 @@ public void GetStatesReturnsEarlyForNonexistentAccount()

tracker.ClearLogs();
Address nonexistent = new PrivateKey().PublicKey.ToAddress();
AddressStateMap result = chain.GetStates(new[] { nonexistent });
AddressStateMap result = chain.GetState(nonexistent);
Assert.False(result.ContainsKey(nonexistent));
var callCount = tracker.Logs.Where(
triple => triple.Item1.Equals("GetBlockStates")
Expand All @@ -987,30 +988,30 @@ public void GetStatesReturnsEarlyForNonexistentAccount()
}

[Fact]
public void GetStatesThrowsIncompleteBlockStatesException()
public void GetStateThrowsIncompleteBlockStatesException()
{
(_, Address[] addresses, BlockChain<DumbAction> chain) =
MakeIncompleteBlockStates();

// As the store has the states for the tip (latest block),
// it shouldn't throw an exception.
Address lastAddress = addresses.Last();
AddressStateMap states = chain.GetStates(new[] { lastAddress });
AddressStateMap states = chain.GetState(lastAddress);
Assert.NotEmpty(states);
Assert.Equal("9", states[lastAddress]);

// As the store lacks the states for blocks other than the tip,
// the following GetStates() calls should throw an exception.
// the following GetState() calls should throw an exception.
foreach (Address addr in addresses.Take(addresses.Length - 1))
{
Assert.Throws<IncompleteBlockStatesException>(() =>
chain.GetStates(new[] { addr })
chain.GetState(addr)
);
}
}

[Fact]
public void GetStatesWithCompletingStates()
public void GetStateWithCompletingStates()
{
(Address signer, Address[] addresses, BlockChain<DumbAction> chain)
= MakeIncompleteBlockStates();
Expand Down Expand Up @@ -1053,7 +1054,7 @@ HashDigest<SHA256>[] ListStateReferences(Address address)
long txNonce = store.GetTxNonce(chain.Id, signer);

store.ClearLogs();
chain.GetStates(new[] { addresses.Last() }, completeStates: true);
chain.GetState(addresses.Last(), completeStates: true);

Assert.Empty(
store.Logs.Where(l => l.Item1 == "StoreStateReference")
Expand All @@ -1064,7 +1065,7 @@ HashDigest<SHA256>[] ListStateReferences(Address address)
}

store.ClearLogs();
chain.GetStates(new[] { addresses[0] }, completeStates: true);
chain.GetState(addresses[0], completeStates: true);

foreach (Block<DumbAction> block in blocks)
{
Expand All @@ -1081,13 +1082,17 @@ HashDigest<SHA256>[] ListStateReferences(Address address)
}

[Fact]
public async void GetStatesReturnsLatestStatesWhenMultipleAddresses()
public async void GetStateReturnsLatestStatesWhenMultipleAddresses()
{
var privateKeys = Enumerable.Range(1, 10).Select(_ => new PrivateKey()).ToList();
var addresses = privateKeys.Select(k => k.PublicKey.ToAddress()).ToList();
var chain = new BlockChain<DumbAction>(new NullPolicy<DumbAction>(), _fx.Store);
var states = chain.GetStates(addresses);
Assert.Equal(new AddressStateMap(), states);

foreach (var address in addresses)
{
var states = chain.GetState(address);
Assert.Equal(new AddressStateMap(), states);
}

var privateKeysAndAddresses10 = privateKeys.Zip(addresses, (k, a) => (k, a));
foreach (var (key, address) in privateKeysAndAddresses10)
Expand All @@ -1096,17 +1101,15 @@ public async void GetStatesReturnsLatestStatesWhenMultipleAddresses()
}

await chain.MineBlock(addresses[0]);
states = chain.GetStates(addresses);

foreach (var address in addresses)
{
Assert.Equal("1", states[address]);
Assert.Equal("1", chain.GetState(address)[address]);
}

chain.MakeTransaction(privateKeys[0], new[] { new DumbAction(addresses[0], "2") });
await chain.MineBlock(addresses[0]);
states = chain.GetStates(addresses);
Assert.Equal("1,2", states[addresses[0]]);
Assert.Equal("1,2", chain.GetState(addresses[0])[addresses[0]]);
}

[Fact]
Expand Down Expand Up @@ -1164,21 +1167,17 @@ public async void EvaluateActions()
ImmutableHashSet<Transaction<TestEvaluateAction>>.Empty.Add(tx1)
);
await chain.MineBlock(_fx.Address1);
var states = chain.GetStates(new[]
{
TestEvaluateAction.SignerKey,
TestEvaluateAction.MinerKey,
TestEvaluateAction.BlockIndexKey,
});

Assert.Equal(
states[TestEvaluateAction.SignerKey],
chain.GetState(TestEvaluateAction.SignerKey)[TestEvaluateAction.SignerKey],
fromAddress.ToHex()
);
Assert.Equal(
states[TestEvaluateAction.MinerKey],
chain.GetState(TestEvaluateAction.MinerKey)[TestEvaluateAction.MinerKey],
_fx.Address1.ToHex());
Assert.Equal(states[TestEvaluateAction.BlockIndexKey], blockIndex);
Assert.Equal(
chain.GetState(TestEvaluateAction.BlockIndexKey)[TestEvaluateAction.BlockIndexKey],
blockIndex);
}

[Fact]
Expand Down Expand Up @@ -1334,21 +1333,24 @@ public async void MineBlockWithBlockAction()
blockChain.MakeTransaction(privateKey2, new[] { new DumbAction(address2, "baz") });
await blockChain.MineBlock(address1);

var states = blockChain.GetStates(new[] { address1, address2 });
var states1 = blockChain.GetState(address1)[address1];
var states2 = blockChain.GetState(address2)[address2];

Assert.Equal(0, blockChain.GetNextTxNonce(address1));
Assert.Equal(1, blockChain.GetNextTxNonce(address2));
Assert.Equal("foo", states[address1]);
Assert.Equal("baz", states[address2]);
Assert.Equal("foo", states1);
Assert.Equal("baz", states2);

blockChain.MakeTransaction(privateKey1, new[] { new DumbAction(address1, "bar") });
await blockChain.MineBlock(address1);
states = blockChain.GetStates(new[] { address1, address2 });

states1 = blockChain.GetState(address1)[address1];
states2 = blockChain.GetState(address2)[address2];

Assert.Equal(1, blockChain.GetNextTxNonce(address1));
Assert.Equal(1, blockChain.GetNextTxNonce(address2));
Assert.Equal("foo,bar,foo", states[address1]);
Assert.Equal("baz", states[address2]);
Assert.Equal("foo,bar,foo", states1);
Assert.Equal("baz", states2);
}

[Fact]
Expand All @@ -1374,7 +1376,7 @@ public void EvaluateBlockAction()
renderActions: false);

var txEvaluations = blocks[1].EvaluateActionsPerTx(a =>
_blockChain.GetStates(new[] { a }, blocks[1].PreviousHash).GetValueOrDefault(a))
_blockChain.GetState(a, blocks[1].PreviousHash).GetValueOrDefault(a))
.Select(te => te.Item2).ToList();
blockActionEvaluation = _blockChain.EvaluateBlockAction(blocks[1], txEvaluations);

Expand All @@ -1392,12 +1394,13 @@ public async void BlockActionWithMultipleAddress()
await _blockChain.MineBlock(miner1);
await _blockChain.MineBlock(miner2);

AddressStateMap states = _blockChain.GetStates(
new[] { miner1, miner2, MinerReward.RewardRecordAddress });
AddressStateMap miner1states = _blockChain.GetState(miner1);
AddressStateMap miner2states = _blockChain.GetState(miner2);
AddressStateMap rewardStates = _blockChain.GetState(rewardRecordAddress);

int reward1 = (int)states[miner1];
int reward2 = (int)states[miner2];
string rewardRecord = (string)states[rewardRecordAddress];
int reward1 = (int)miner1states[miner1];
int reward2 = (int)miner2states[miner2];
string rewardRecord = (string)rewardStates[rewardRecordAddress];

Assert.Equal(2, reward1);
Assert.Equal(1, reward2);
Expand All @@ -1407,7 +1410,7 @@ public async void BlockActionWithMultipleAddress()

/// <summary>
/// Builds a fixture that has incomplete states for blocks other
/// than the tip, to test <c>GetStates()</c> method's
/// than the tip, to test <c>GetState()</c> method's
/// <c>completeStates: true</c> option and
/// <see cref="IncompleteBlockStatesException"/>.
///
Expand Down
22 changes: 11 additions & 11 deletions Libplanet.Tests/Net/SwarmTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ public async Task InitialBlockDownloadStates()

await receiverSwarm.PreloadAsync(trustedStateValidators: trustedStateValidators);
await receiverSwarm.PreloadAsync(true);
var states = receiverChain.GetStates(new[] { address });
var states = receiverChain.GetState(address);

Assert.Equal("foo,bar,baz", states[address]);
Assert.Equal(minerChain.AsEnumerable(), receiverChain.AsEnumerable());
Expand Down Expand Up @@ -1655,8 +1655,8 @@ public async Task PreloadWithTrustedPeers(bool trust, bool genesisWithAction)
foreach (BlockChain<DumbAction> chain in new[] { minerChain, receiverChain })
{
var chainType = ReferenceEquals(chain, minerChain) ? "M" : "R";
var states = chain.GetStates(
new[] { target },
var states = chain.GetState(
target,
completeStates: false
);
Assert.Single(states);
Expand All @@ -1666,8 +1666,8 @@ public async Task PreloadWithTrustedPeers(bool trust, bool genesisWithAction)
);
}

AddressStateMap TryToGetDeepStates() => receiverChain.GetStates(
new[] { target },
AddressStateMap TryToGetDeepStates() => receiverChain.GetState(
target,
deepBlockHash,
completeStates: false
);
Expand All @@ -1692,8 +1692,8 @@ AddressStateMap TryToGetDeepStates() => receiverChain.GetStates(
{
foreach (BlockChain<DumbAction> chain in new[] { minerChain, receiverChain })
{
var states = chain.GetStates(
new[] { genesisTarget },
var states = chain.GetState(
genesisTarget,
completeStates: false
);
Assert.Single(states);
Expand All @@ -1703,8 +1703,8 @@ AddressStateMap TryToGetDeepStates() => receiverChain.GetStates(

foreach (BlockChain<DumbAction> chain in new[] { minerChain, receiverChain })
{
var minerState = chain.GetStates(
new[] { minerSwarm.Address },
var minerState = chain.GetState(
minerSwarm.Address,
completeStates: false);
Assert.Single(minerState);
Assert.Equal(
Expand Down Expand Up @@ -1835,7 +1835,7 @@ await receiverSwarm.PreloadAsync(
{
Assert.Equal(receiverChainId, receiverChain.Id);
Assert.Null(receiverChain.Tip);
Assert.Null(receiverChain.GetStates(new[] { address }).GetValueOrDefault(address));
Assert.Null(receiverChain.GetState(address).GetValueOrDefault(address));
}
else
{
Expand All @@ -1848,7 +1848,7 @@ await receiverSwarm.PreloadAsync(
string.Join(",", Enumerable.Range(0, 5).Select(j => $"Item{i}.{j}"))
)
),
receiverChain.GetStates(new[] { address })[address]
receiverChain.GetState(address)[address]
);
}
}
Expand Down
Loading