/// <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 {nameof(PruneStates)}()"); var survivalNodes = new HashSet <HashDigest <SHA256> >(); foreach (HashDigest <SHA256> stateRootHash in survivingStateRootHashes) { var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(stateRootHash), _secure ); _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(); }
public void PruneStates(IImmutableSet <HashDigest <SHA256> > survivingStateRootHashes) { var stopwatch = new Stopwatch(); _logger.Verbose($"Started {nameof(PruneStates)}()"); var survivalNodes = new HashSet <HashDigest <SHA256> >(); foreach (HashDigest <SHA256> stateRootHash in survivingStateRootHashes) { var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(stateRootHash), _secure ); _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()) { if (survivalNodes.Contains(new HashDigest <SHA256>(stateKey))) { continue; } _stateKeyValueStore.Delete(stateKey); ++deleteCount; } _logger.Debug( "Finished to clean up {DeleteCount} state hashes " + "(elapsed: {ElapsedMilliseconds} ms).", deleteCount, stopwatch.ElapsedMilliseconds); stopwatch.Stop(); }
public void PruneStates(ImmutableHashSet <HashDigest <SHA256> > excludeBlockHashes) { var stopwatch = new Stopwatch(); Log.Verbose($"Started {nameof(PruneStates)}()"); var excludeNodes = new HashSet <HashDigest <SHA256> >(); foreach (var blockHash in excludeBlockHashes) { if (!_stateHashKeyValueStore.Exists(blockHash.ToByteArray())) { continue; } byte[] stateRootHashBytes = _stateHashKeyValueStore.Get(blockHash.ToByteArray()); var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(new HashDigest <SHA256>(stateRootHashBytes)), _secure); Log.Debug("Started to iterate hash nodes."); stopwatch.Start(); foreach (HashDigest <SHA256> nodeHash in stateTrie.IterateHashNodes()) { excludeNodes.Add(nodeHash); } Log.Debug( "Finished to iterate hash nodes (elapsed: {ElapsedMilliseconds} ms).", stopwatch.ElapsedMilliseconds); stopwatch.Stop(); } Log.Debug("{Count} hash nodes are excluded.", excludeNodes.Count); // Clean up nodes. long deleteCount = 0; Log.Debug("Started to clean up states."); stopwatch.Restart(); foreach (var stateKey in _stateKeyValueStore.ListKeys()) { if (excludeNodes.Contains(new HashDigest <SHA256>(stateKey))) { continue; } _stateKeyValueStore.Delete(stateKey); ++deleteCount; } Log.Debug( "Finished to clean up {DeleteCount} state hashes " + "(elapsed: {ElapsedMilliseconds} ms).", deleteCount, stopwatch.ElapsedMilliseconds); stopwatch.Stop(); // Clean up state root hashes. deleteCount = 0; Log.Debug("Started to clean up state hashes."); stopwatch.Restart(); foreach (var stateHashKey in _stateHashKeyValueStore.ListKeys()) { if (excludeBlockHashes.Contains(new HashDigest <SHA256>(stateHashKey))) { continue; } _stateHashKeyValueStore.Delete(stateHashKey); ++deleteCount; } Log.Debug( "Finished to clean up {DeleteCount} states (elapsed: {ElapsedMilliseconds} ms).", deleteCount, stopwatch.ElapsedMilliseconds); stopwatch.Stop(); }