Skip to content

Commit

Permalink
Merge pull request #346 from earlbread/fix-get-states-multiple-address
Browse files Browse the repository at this point in the history
Fix GetStates bug when there are multiple addresses
  • Loading branch information
earlbread authored Jul 11, 2019
2 parents bd94d57 + 06aab2d commit 9e0b7fc
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 35 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ Version 0.4.1

To be released.

### Bug fixes

- Fixed a bug where the `BlockChain<T>.GetStates()` method had not returned
the latest state when there are multiple addresses. [[#346]]

[#346]: https://github.com/planetarium/libplanet/pull/346

Version 0.4.0
-------------
Expand Down
49 changes: 39 additions & 10 deletions Libplanet.Tests/Blockchain/BlockChainTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -416,21 +416,21 @@ public void ForkStateReferences()
forked.Append(fb2);

Assert.Equal(
b1.Hash,
forked.Store.LookupStateReference(fId, addr1, forked.Tip));
Tuple.Create(b1.Hash, b1.Index),
forked.Store.LookupStateReferenceWithIndex(fId, addr1, forked.Tip));
Assert.Null(
forked.Store.LookupStateReference(fId, addr2, forked.Tip));
forked.Store.LookupStateReferenceWithIndex(fId, addr2, forked.Tip));

// Fork from b2.
forked = _blockChain.Fork(b2.Hash);
fId = forked.Id.ToString();

Assert.Equal(
b1.Hash,
forked.Store.LookupStateReference(fId, addr1, forked.Tip));
Tuple.Create(b1.Hash, b1.Index),
forked.Store.LookupStateReferenceWithIndex(fId, addr1, forked.Tip));
Assert.Equal(
b2.Hash,
forked.Store.LookupStateReference(fId, addr2, forked.Tip));
Tuple.Create(b2.Hash, b2.Index),
forked.Store.LookupStateReferenceWithIndex(fId, addr2, forked.Tip));
}

[Fact]
Expand Down Expand Up @@ -786,9 +786,9 @@ HashDigest<SHA256>[] ListStateReferences(Address address)

while (true)
{
HashDigest<SHA256>? sr =
store.LookupStateReference(@namespace, address, block);
if (sr is HashDigest<SHA256> reference)
Tuple<HashDigest<SHA256>, long> sr =
store.LookupStateReferenceWithIndex(@namespace, address, block);
if (sr?.Item1 is HashDigest<SHA256> reference)
{
refs.Add(reference);
block = chain.Blocks[reference];
Expand Down Expand Up @@ -842,6 +842,35 @@ HashDigest<SHA256>[] ListStateReferences(Address address)
}
}

[Fact]
public void GetStatesReturnsLatestStatesWhenMultipleAddresses()
{
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);

var privateKeysAndAddresses10 = privateKeys.Zip(addresses, (k, a) => (k, a));
foreach (var (key, address) in privateKeysAndAddresses10)
{
chain.MakeTransaction(key, new[] { new DumbAction(address, "1") });
}

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

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

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

[Fact]
public void EvaluateActions()
{
Expand Down
29 changes: 15 additions & 14 deletions Libplanet.Tests/Store/StoreExtensionTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Libplanet.Blocks;
using Libplanet.Tests.Common.Action;
using Libplanet.Tx;
Expand Down Expand Up @@ -46,31 +46,32 @@ public void LookupStateReference(StoreFixture fx)
fx.Store.StoreStateReference(fx.StoreNamespace, tx4.UpdatedAddresses, block4);
Assert.Null(fx.Store.LookupStateReference(fx.StoreNamespace, address, fx.Block3));
Assert.Equal(
block4.Hash,
fx.Store.LookupStateReference(fx.StoreNamespace, address, block4)
Tuple.Create(block4.Hash, block4.Index),
fx.Store.LookupStateReferenceWithIndex(fx.StoreNamespace, address, block4)
);
Assert.Equal(
block4.Hash,
fx.Store.LookupStateReference(fx.StoreNamespace, address, block5)
Tuple.Create(block4.Hash, block4.Index),
fx.Store.LookupStateReferenceWithIndex(fx.StoreNamespace, address, block5)
);
Assert.Equal(
block4.Hash,
fx.Store.LookupStateReference(fx.StoreNamespace, address, block6)
Tuple.Create(block4.Hash, block4.Index),
fx.Store.LookupStateReferenceWithIndex(fx.StoreNamespace, address, block6)
);

fx.Store.StoreStateReference(fx.StoreNamespace, tx5.UpdatedAddresses, block5);
Assert.Null(fx.Store.LookupStateReference(fx.StoreNamespace, address, fx.Block3));
Assert.Null(fx.Store.LookupStateReferenceWithIndex(
fx.StoreNamespace, address, fx.Block3));
Assert.Equal(
block4.Hash,
fx.Store.LookupStateReference(fx.StoreNamespace, address, block4)
Tuple.Create(block4.Hash, block4.Index),
fx.Store.LookupStateReferenceWithIndex(fx.StoreNamespace, address, block4)
);
Assert.Equal(
block5.Hash,
fx.Store.LookupStateReference(fx.StoreNamespace, address, block5)
Tuple.Create(block5.Hash, block5.Index),
fx.Store.LookupStateReferenceWithIndex(fx.StoreNamespace, address, block5)
);
Assert.Equal(
block5.Hash,
fx.Store.LookupStateReference(fx.StoreNamespace, address, block6)
Tuple.Create(block5.Hash, block5.Index),
fx.Store.LookupStateReferenceWithIndex(fx.StoreNamespace, address, block6)
);
}
}
Expand Down
12 changes: 6 additions & 6 deletions Libplanet.Tests/Store/StoreTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,14 @@ public void ForkStateReferences(int branchPointIndex)
blocks[3]);

Assert.Equal(
blocks[2].Hash,
Fx.Store.LookupStateReference(Fx.StoreNamespace, address1, blocks[3]));
Tuple.Create(blocks[2].Hash, blocks[2].Index),
Fx.Store.LookupStateReferenceWithIndex(Fx.StoreNamespace, address1, blocks[3]));
Assert.Equal(
blocks[3].Hash,
Fx.Store.LookupStateReference(Fx.StoreNamespace, address2, blocks[3]));
Tuple.Create(blocks[3].Hash, blocks[3].Index),
Fx.Store.LookupStateReferenceWithIndex(Fx.StoreNamespace, address2, blocks[3]));
Assert.Equal(
blocks[branchPointIndex].Hash,
Fx.Store.LookupStateReference(targetNamespace, address1, blocks[3]));
Tuple.Create(blocks[branchPointIndex].Hash, blocks[branchPointIndex].Index),
Fx.Store.LookupStateReferenceWithIndex(targetNamespace, address1, blocks[3]));
Assert.Null(
Fx.Store.LookupStateReference(targetNamespace, address2, blocks[3]));
}
Expand Down
12 changes: 8 additions & 4 deletions Libplanet/Blockchain/BlockChain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,22 @@ public AddressStateMap GetStates(

ImmutableHashSet<Address> requestedAddresses =
addresses.ToImmutableHashSet();
var hashValues = new HashSet<HashDigest<SHA256>>();
var stateReferences = new HashSet<Tuple<HashDigest<SHA256>, long>>();

foreach (var address in requestedAddresses)
{
var hashDigest = Store.LookupStateReference(
Tuple<HashDigest<SHA256>, long> sr = Store.LookupStateReferenceWithIndex(
Id.ToString(), address, block);
if (!(hashDigest is null))
if (!(sr is null))
{
hashValues.Add(hashDigest.Value);
stateReferences.Add(sr);
}
}

IEnumerable<HashDigest<SHA256>> hashValues = stateReferences
.OrderByDescending(sr => sr.Item2)
.Select(sr => sr.Item1);

foreach (var hashValue in hashValues)
{
AddressStateMap blockStates = Store.GetBlockStates(hashValue);
Expand Down
15 changes: 14 additions & 1 deletion Libplanet/Store/StoreExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ public static class StoreExtension
Address address,
Block<T> lookupUntil)
where T : IAction, new()
{
Tuple<HashDigest<SHA256>, long> sr = store.
LookupStateReferenceWithIndex(@namespace, address, lookupUntil);

return sr?.Item1;
}

internal static Tuple<HashDigest<SHA256>, long> LookupStateReferenceWithIndex<T>(
this IStore store,
string @namespace,
Address address,
Block<T> lookupUntil)
where T : IAction, new()
{
if (lookupUntil is null)
{
Expand All @@ -43,7 +56,7 @@ public static class StoreExtension
{
if (pair.Item2 <= lookupUntil.Index)
{
return pair.Item1;
return Tuple.Create(pair.Item1, pair.Item2);
}
}

Expand Down

0 comments on commit 9e0b7fc

Please sign in to comment.