Skip to content

Commit

Permalink
Merge pull request #3614 from greymistcube/refactor/remove-prune-states
Browse files Browse the repository at this point in the history
♻️ 🧹 Removed `IStateStore.PruneStates()`
  • Loading branch information
greymistcube authored Jan 18, 2024
2 parents 3164228 + 8eb0b14 commit 7323bbd
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 123 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ To be released.

- (Libplanet.Store) Changed `IStateStore.Commit()` to return an `ITrie`
with either its `Root` as `null` or a `HashNode`. [[#3610]]
- (Libplanet.Store) Removed `IStateStore.PruneStates()` method.
[[#3613], [#3614]]

[#3610]: https://github.com/planetarium/libplanet/pull/3610
[#3613]: https://github.com/planetarium/libplanet/issues/3613
[#3614]: https://github.com/planetarium/libplanet/pull/3614

Version 3.9.4
-------------
Expand Down
4 changes: 0 additions & 4 deletions Libplanet.Explorer.Executable/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -440,10 +440,6 @@ private class NoOpStateStore : IStateStore
{
public ITrie GetStateRoot(HashDigest<SHA256>? stateRootHash) => null;

public void PruneStates(IImmutableSet<HashDigest<SHA256>> survivingStateRootHashes)
{
}

public ITrie Commit(ITrie trie) => null;

public void Dispose()
Expand Down
7 changes: 0 additions & 7 deletions Libplanet.Store/IStateStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@ public interface IStateStore : IDisposable
/// If <see langword="null"/> is passed the empty state root trie is returned.</returns>
ITrie GetStateRoot(HashDigest<SHA256>? stateRootHash);

/// <summary>
/// Prunes the states no more used from the state store.
/// </summary>
/// <param name="survivingStateRootHashes">The state root hashes <em>not</em> to prune.
/// These state root hashes are guaranteed to survive after pruning.</param>
void PruneStates(IImmutableSet<HashDigest<SHA256>> survivingStateRootHashes);

/// <summary>
/// Commits given <paramref name="trie"/> to storage.
/// Returned <see cref="ITrie"/> must be identical to the one obtained from
Expand Down
55 changes: 0 additions & 55 deletions Libplanet.Store/TrieStateStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,61 +33,6 @@ public TrieStateStore(IKeyValueStore stateKeyValueStore)

public IKeyValueStore StateKeyValueStore { get; }

/// <inheritdoc cref="IStateStore.PruneStates(IImmutableSet{HashDigest{SHA256}})"/>
public void PruneStates(IImmutableSet<HashDigest<SHA256>> survivingStateRootHashes)
{
// 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. https://github.com/planetarium/libplanet/issues/1653
var stopwatch = new Stopwatch();
_logger.Verbose("Started {MethodName}()", nameof(PruneStates));
var survivalNodes = new HashSet<HashDigest<SHA256>>();
foreach (HashDigest<SHA256> stateRootHash in survivingStateRootHashes)
{
var stateTrie = new MerkleTrie(
StateKeyValueStore,
new HashNode(stateRootHash));
_logger.Debug("Started to iterate hash nodes");
stopwatch.Start();
foreach (HashDigest<SHA256> nodeHash in stateTrie.IterateHashNodes())
{
survivalNodes.Add(nodeHash);
}

_logger.Debug(
"Finished to iterate hash nodes (elapsed: {ElapsedMilliseconds} ms)",
stopwatch.ElapsedMilliseconds);
stopwatch.Stop();
}

_logger.Debug("{Count} hash nodes will survive", survivalNodes.Count);

// Clean up nodes.
long deleteCount = 0;
_logger.Debug("Started to clean up states...");
stopwatch.Restart();
foreach (var stateKey in StateKeyValueStore.ListKeys())
{
// FIXME: Bencodex fingerprints also should be tracked.
// https://github.com/planetarium/libplanet/issues/1653
if (stateKey.Length != HashDigest<SHA256>.Size ||
survivalNodes.Contains(new HashDigest<SHA256>(stateKey.ByteArray)))
{
continue;
}

StateKeyValueStore.Delete(stateKey);
++deleteCount;
}

_logger.Debug(
"Finished to clean up {DeleteCount} state hashes " +
"(elapsed: {ElapsedMilliseconds} ms)",
deleteCount,
stopwatch.ElapsedMilliseconds);
stopwatch.Stop();
}

/// <summary>
/// Copies states under state root hashes of given <paramref name="stateRootHashes"/>
/// to <paramref name="targetStateStore"/>.
Expand Down
25 changes: 16 additions & 9 deletions Libplanet.Tests/Blockchain/BlockChainTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1660,13 +1660,9 @@ public void BlockActionWithMultipleAddress()
/// </summary>
/// <param name="store">store.</param>
/// <param name="stateStore">State Store.</param>
/// <param name="renderer">Renderer.</param>
/// <returns>Tuple of addresses and chain.</returns>
internal static (Address, Address[] Addresses, BlockChain Chain)
MakeIncompleteBlockStates(
IStore store,
IStateStore stateStore,
IRenderer renderer = null)
MakeIncompleteBlockStates(IStore store, IStateStore stateStore)
{
List<int> presentIndices = new List<int>() { 4, 7 };
List<Block> presentBlocks = new List<Block>();
Expand All @@ -1689,7 +1685,7 @@ internal static (Address, Address[] Addresses, BlockChain Chain)
store,
stateStore,
genesisBlock,
renderers: renderer is null ? null : new[] { renderer },
renderers: null,
blockChainStates: chainStates,
actionEvaluator: actionEvaluator);
var privateKey = new PrivateKey();
Expand Down Expand Up @@ -1747,11 +1743,22 @@ void BuildIndex(Guid id, Block block)
}
}

stateStore.PruneStates(
IStateStore incompleteStateStore = new TrieStateStore(new MemoryKeyValueStore());
((TrieStateStore)stateStore).CopyStates(
ImmutableHashSet<HashDigest<SHA256>>.Empty
.Add(presentBlocks[0].StateRootHash)
.Add(presentBlocks[1].StateRootHash)
);
.Add(presentBlocks[1].StateRootHash),
(TrieStateStore)incompleteStateStore);

chain = new BlockChain(
blockPolicy,
new VolatileStagePolicy(),
store,
incompleteStateStore,
genesisBlock,
renderers: null,
blockChainStates: chainStates,
actionEvaluator: actionEvaluator);

return (signer, addresses, chain);
}
Expand Down
7 changes: 0 additions & 7 deletions Libplanet.Tests/Store/StateStoreTracker.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Collections.Immutable;
using System.Security.Cryptography;
using Libplanet.Common;
using Libplanet.Store;
Expand All @@ -22,12 +21,6 @@ public ITrie GetStateRoot(HashDigest<SHA256>? stateRootHash)
return _stateStore.GetStateRoot(stateRootHash);
}

public void PruneStates(IImmutableSet<HashDigest<SHA256>> survivingStateRootHashes)
{
Log(nameof(PruneStates), survivingStateRootHashes);
_stateStore.PruneStates(survivingStateRootHashes);
}

public ITrie Commit(ITrie trie)
{
Log(nameof(Commit), trie.Hash);
Expand Down
41 changes: 0 additions & 41 deletions Libplanet.Tests/Store/TrieStateStoreTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,47 +66,6 @@ public void GetStateRoot()
Assert.Null(found.Get(new[] { KeyQuux })[0]);
}

[Fact]
public void PruneStates()
{
var values = ImmutableDictionary<KeyBytes, IValue>.Empty
.Add(new KeyBytes("foo"), (Binary)GetRandomBytes(4096))
.Add(
new KeyBytes("bar"),
(Text)ByteUtil.Hex(GetRandomBytes(2048)))
.Add(new KeyBytes("baz"), (Bencodex.Types.Boolean)false)
.Add(new KeyBytes("qux"), Bencodex.Types.Dictionary.Empty)
.Add(
new KeyBytes("zzz"),
Bencodex.Types.Dictionary.Empty
.Add("binary", GetRandomBytes(4096))
.Add("text", ByteUtil.Hex(GetRandomBytes(2048))));

var stateStore = new TrieStateStore(_stateKeyValueStore);
ITrie first = stateStore.Commit(
values.Aggregate(
stateStore.GetStateRoot(null),
(prev, kv) => prev.Set(kv.Key, kv.Value)));

int prevStatesCount = _stateKeyValueStore.ListKeys().Count();
ImmutableDictionary<KeyBytes, IValue> nextState =
values.SetItem(new KeyBytes("foo"), (Binary)GetRandomBytes(4096));
ITrie second = stateStore.Commit(
nextState.Aggregate(
first,
(prev, kv) => prev.Set(kv.Key, kv.Value)));

// foo = 0x666f6f
// updated branch node (0x6, aka root) + updated branch node (0x66) +
// updated short node + new value nodes
Assert.Equal(prevStatesCount + 4, _stateKeyValueStore.ListKeys().Count());

stateStore.PruneStates(ImmutableHashSet<HashDigest<SHA256>>.Empty.Add(second.Hash));

// It will stay at the same count of nodes.
Assert.Equal(prevStatesCount, _stateKeyValueStore.ListKeys().Count());
}

[Fact]
public void CopyStates()
{
Expand Down

0 comments on commit 7323bbd

Please sign in to comment.