diff --git a/CHANGES.md b/CHANGES.md index 072acafbc2d..3b9651ad08f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,13 @@ Libplanet changelog Version 0.23.1 -------------- -To be released. +Released on December 10, 2021. + + - Fixed `TrieStateStore.PruneStates()` method's bug that it had thrown + `ArgumentOutOfRangeException`. [[#1653], [#1654]] + +[#1653]: https://github.com/planetarium/libplanet/issues/1653 +[#1654]: https://github.com/planetarium/libplanet/pull/1654 Version 0.23.0 diff --git a/Libplanet.Tests/Store/TrieStateStoreTest.cs b/Libplanet.Tests/Store/TrieStateStoreTest.cs index 104f3ff8edf..c0804e20705 100644 --- a/Libplanet.Tests/Store/TrieStateStoreTest.cs +++ b/Libplanet.Tests/Store/TrieStateStoreTest.cs @@ -68,28 +68,35 @@ public void GetStateRoot(bool secure) public void PruneStates(bool secure) { var values = ImmutableDictionary.Empty - .Add("foo", (Binary)GetRandomBytes(32)) - .Add("bar", (Text)ByteUtil.Hex(GetRandomBytes(32))) + .Add("foo", (Binary)GetRandomBytes(4096)) + .Add("bar", (Text)ByteUtil.Hex(GetRandomBytes(2048))) .Add("baz", (Bencodex.Types.Boolean)false) - .Add("qux", Bencodex.Types.Dictionary.Empty); + .Add("qux", Bencodex.Types.Dictionary.Empty) + .Add( + "zzz", + Bencodex.Types.Dictionary.Empty + .Add("binary", GetRandomBytes(4096)) + .Add("text", ByteUtil.Hex(GetRandomBytes(2048)))); var stateStore = new TrieStateStore(_stateKeyValueStore, secure); ITrie first = stateStore.Commit(null, values); int prevStatesCount = _stateKeyValueStore.ListKeys().Count(); ImmutableDictionary nextStates = - values.SetItem("foo", (Binary)GetRandomBytes(32)); + values.SetItem("foo", (Binary)GetRandomBytes(4096)); ITrie second = stateStore.Commit(first.Hash, nextStates); // foo = 0x666f6f // updated branch node (0x6, aka root) + updated branch node (0x66) + - // updated short node + new value node - Assert.Equal(prevStatesCount + 4, _stateKeyValueStore.ListKeys().Count()); + // updated short node + new value nodes + Assert.Equal(prevStatesCount + 5, _stateKeyValueStore.ListKeys().Count()); stateStore.PruneStates(ImmutableHashSet>.Empty.Add(second.Hash)); // It will stay at the same count of nodes. - Assert.Equal(prevStatesCount, _stateKeyValueStore.ListKeys().Count()); + // FIXME: Bencodex fingerprints also should be tracked. + // https://github.com/planetarium/libplanet/issues/1653 + Assert.Equal(prevStatesCount + 1, _stateKeyValueStore.ListKeys().Count()); } [Fact] diff --git a/Libplanet/Store/TrieStateStore.cs b/Libplanet/Store/TrieStateStore.cs index 765d1ea40e8..9cb8412df6f 100644 --- a/Libplanet/Store/TrieStateStore.cs +++ b/Libplanet/Store/TrieStateStore.cs @@ -40,7 +40,7 @@ public void PruneStates(IImmutableSet> survivingStateRootHash { // TODO: As MerkleTrie now have two levels of Merkle trees (one for accounts and one for // Bencodex values), it needs to be fixed so that it can prune offloaded Bencodex - // values too. + // values too. https://github.com/planetarium/libplanet/issues/1653 var stopwatch = new Stopwatch(); _logger.Verbose($"Started {nameof(PruneStates)}()"); var survivalNodes = new HashSet>(); @@ -72,7 +72,10 @@ public void PruneStates(IImmutableSet> survivingStateRootHash stopwatch.Restart(); foreach (var stateKey in _stateKeyValueStore.ListKeys()) { - if (survivalNodes.Contains(new HashDigest(stateKey))) + // FIXME: Bencodex fingerprints also should be tracked. + // https://github.com/planetarium/libplanet/issues/1653 + if (stateKey.Length != HashDigest.Size || + survivalNodes.Contains(new HashDigest(stateKey))) { continue; }