public void SetStates <T>( Block <T> block, IImmutableDictionary <string, IValue> states) where T : IAction, new() { MerkleTrie prevStatesTrie; var previousBlockStateHashBytes = block.PreviousHash is null ? null : _stateHashKeyValueStore.Get(block.PreviousHash.Value.ToByteArray()); var trieRoot = previousBlockStateHashBytes is null ? null : new HashNode(new HashDigest <SHA256>(previousBlockStateHashBytes)); prevStatesTrie = new MerkleTrie(_stateKeyValueStore, trieRoot); foreach (var pair in states) { prevStatesTrie.Set(Encoding.UTF8.GetBytes(pair.Key), pair.Value); } var newStateTrie = prevStatesTrie.Commit(); _stateHashKeyValueStore.Set( block.Hash.ToByteArray(), newStateTrie.Root !.Hash().ToByteArray()); }
public void DifferentNodes() { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); MerkleTrie trieA = new MerkleTrie(keyValueStore), trieB = new MerkleTrie(keyValueStore); trieA = (MerkleTrie)trieA.Set(new KeyBytes(0x01), Null.Value) .Set(new KeyBytes(0x02), Null.Value) .Set(new KeyBytes(0x03), Null.Value) .Commit(); trieB = (MerkleTrie)trieB.Set(new KeyBytes(0x01), Dictionary.Empty) .Set(new KeyBytes(0x02), Null.Value) .Set(new KeyBytes(0x04), Null.Value) .Commit(); Dictionary <KeyBytes, (IValue OriginValue, IValue OtherValue)> differentNodes = trieA.DifferentNodes(trieB).ToDictionary( diff => diff.Key, diff => (diff.OriginValue, diff.OtherValue)); Assert.Equal(2, differentNodes.Count); Assert.NotNull(differentNodes[new KeyBytes(1)].OtherValue); Assert.False(differentNodes.ContainsKey(new KeyBytes(2))); Assert.Null(differentNodes[new KeyBytes(3)].OtherValue); Assert.False(differentNodes.ContainsKey(new KeyBytes(4))); }
public void ListAllStates() { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); MerkleTrie trie = new MerkleTrie(keyValueStore); trie = (MerkleTrie)trie.Set(new KeyBytes(0x01), Null.Value) .Set(new KeyBytes(0x02), Null.Value) .Set(new KeyBytes(0x03), Null.Value) .Set(new KeyBytes(0x04), Null.Value) .Set(new KeyBytes(0xbe, 0xef), Dictionary.Empty); Dictionary <KeyBytes, IValue> states = trie.ListAllStates().ToDictionary(pair => pair.Key, pair => pair.Value); Assert.Equal(5, states.Count); Assert.Equal(Null.Value, states[new KeyBytes(0x01)]); Assert.Equal(Null.Value, states[new KeyBytes(0x02)]); Assert.Equal(Null.Value, states[new KeyBytes(0x03)]); Assert.Equal(Null.Value, states[new KeyBytes(0x04)]); Assert.Equal(Dictionary.Empty, states[new KeyBytes(0xbe, 0xef)]); trie = (MerkleTrie)trie.Commit(); states = trie.ListAllStates().ToDictionary(pair => pair.Key, pair => pair.Value); Assert.Equal(5, states.Count); Assert.Equal(Null.Value, states[new KeyBytes(0x01)]); Assert.Equal(Null.Value, states[new KeyBytes(0x02)]); Assert.Equal(Null.Value, states[new KeyBytes(0x03)]); Assert.Equal(Null.Value, states[new KeyBytes(0x04)]); Assert.Equal(Dictionary.Empty, states[new KeyBytes(0xbe, 0xef)]); }
public void Query( [Argument( Name = "KV-STORE", Description = KVStoreArgumentDescription)] string kvStoreUri, [Argument( Name = "STATE-ROOT-HASH", Description = "The state root hash to compare.")] string stateRootHashHex, [Argument( Name = "STATE-KEY", Description = "The key of the state to query.")] string stateKey, [FromService] IConfigurationService <ToolConfiguration> configurationService) { ToolConfiguration toolConfiguration = configurationService.Load(); kvStoreUri = ConvertKVStoreUri(kvStoreUri, toolConfiguration); IKeyValueStore keyValueStore = LoadKVStoreFromURI(kvStoreUri); var trie = new MerkleTrie( keyValueStore, HashDigest <SHA256> .FromString(stateRootHashHex)); byte[] stateKeyBytes = Encoding.UTF8.GetBytes(stateKey); if (trie.TryGet( stateKeyBytes, out IValue? value) && value is { })
/// <summary> /// Copies states under state root hashes of given <paramref name="stateRootHashes"/> /// to <paramref name="targetStateStore"/>. /// </summary> /// <param name="stateRootHashes">The state root hashes of states to copy.</param> /// <param name="targetStateStore">The target state store to copy state root hashes.</param> public void CopyStates( IImmutableSet <HashDigest <SHA256> > stateRootHashes, TrieStateStore targetStateStore) { IKeyValueStore targetKeyValueStore = targetStateStore._stateKeyValueStore; var stopwatch = new Stopwatch(); _logger.Verbose($"Started {nameof(CopyStates)}()"); stopwatch.Start(); foreach (HashDigest <SHA256> stateRootHash in stateRootHashes) { var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(stateRootHash), _secure ); foreach (var(key, value) in stateTrie.IterateNodeKeyValuePairs()) { targetKeyValueStore.Set(key, value); } } stopwatch.Stop(); _logger.Debug( "Finished to copy all states {ElapsedMilliseconds} ms", stopwatch.ElapsedMilliseconds); _logger.Verbose($"Finished {nameof(CopyStates)}()"); }
public void GetAndSet(int addressCount) { ITrie trie = new MerkleTrie(new MemoryKeyValueStore()); var addresses = Enumerable .Range(0, addressCount) .Select(_ => new PrivateKey().ToAddress()) .ToImmutableArray(); var states = new Dictionary <Address, IValue>(); void CheckAddressStates() { foreach (var address in addresses) { Assert.Equal( states.ContainsKey(address), trie.TryGet(address.ToByteArray(), out IValue state)); IValue expectedState = states.ContainsKey(address) ? states[address] : null; Assert.Equal(expectedState, state); } } foreach (var address in addresses) { states[address] = (Text)address.ToHex(); trie = trie.Set(address.ToByteArray(), states[address]); CheckAddressStates(); } }
internal HashDigest <SHA256> EvalState <T>( Block <T> block, IImmutableDictionary <string, IValue> states, bool rehearsal = false) where T : IAction, new() { ITrie prevStatesTrie; var previousBlockStateHashBytes = block.PreviousHash is null ? null : _stateHashKeyValueStore.Get(block.PreviousHash.Value.ToByteArray()); var trieRoot = previousBlockStateHashBytes is null ? null : new HashNode(new HashDigest <SHA256>(previousBlockStateHashBytes)); prevStatesTrie = new MerkleTrie(_stateKeyValueStore, trieRoot, _secure); foreach (var pair in states) { prevStatesTrie = prevStatesTrie.Set(Encoding.UTF8.GetBytes(pair.Key), pair.Value); } var newStateTrie = prevStatesTrie.Commit(rehearsal); return(newStateTrie.Hash); }
public void Export( [Argument( Name = "KV-STORE", Description = KVStoreArgumentDescription)] string kvStoreUri, [Argument( Name = "STATE-ROOT-HASH", Description = "The state root hash to compare.")] string stateRootHashHex, [FromService] IConfigurationService <ToolConfiguration> configurationService) { ToolConfiguration toolConfiguration = configurationService.Load(); kvStoreUri = ConvertKVStoreUri(kvStoreUri, toolConfiguration); IKeyValueStore keyValueStore = LoadKVStoreFromURI(kvStoreUri); var trie = new MerkleTrie( keyValueStore, HashDigest <SHA256> .FromString(stateRootHashHex)); var codec = new Codec(); ImmutableDictionary <string, byte[]> decoratedStates = trie.ListAllStates() .ToImmutableDictionary( pair => Encoding.UTF8.GetString(pair.Key.ToArray()), pair => codec.Encode(pair.Value)); Console.WriteLine(JsonSerializer.Serialize(decoratedStates)); }
public void ConstructWithRootNode() { var hashDigest = new HashDigest <SHA256>(GetRandomBytes(Size)); INode rootNode = new HashNode(hashDigest); var merkleTrie = new MerkleTrie(new MemoryKeyValueStore(), rootNode); Assert.Equal(hashDigest, merkleTrie.Hash); }
/// <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 ThrowArgumentNullExceptionWhenSettingNull() { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); ITrie trie = new MerkleTrie(keyValueStore); Assert.Throws <ArgumentNullException>( () => trie.Set(new KeyBytes(0xbe, 0xef), null) ); }
public void ThrowArgumentNullExceptionWhenSettingNull() { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); ITrie trie = new MerkleTrie(keyValueStore); Assert.Throws <ArgumentNullException>(() => { _ = trie.Set(new byte[] { 0xbe, 0xef }, null); }); }
public void ConstructWithHashDigest() { var hashDigest = new HashDigest <SHA256>(GetRandomBytes(Size)); var merkleTrie = new MerkleTrie(new MemoryKeyValueStore(), hashDigest); Assert.Equal(hashDigest, merkleTrie.Hash); // See https://github.com/planetarium/libplanet/pull/1091 merkleTrie = new MerkleTrie(new MemoryKeyValueStore(), MerkleTrie.EmptyRootHash); Assert.Null(merkleTrie.Root); }
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 IValue?GetState(string stateKey, BlockHash?blockHash = null, Guid?chainId = null) { if (blockHash is null) { throw new ArgumentNullException(nameof(blockHash)); } var stateHash = _stateHashKeyValueStore.Get(blockHash?.ToByteArray() !); var stateTrie = new MerkleTrie( _stateKeyValueStore, new HashNode(new HashDigest <SHA256>(stateHash)), _secure); var key = Encoding.UTF8.GetBytes(stateKey); return(stateTrie.TryGet(key, out IValue? value) ? value : null); }
public void EmptyRootHash() { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); ITrie trie = new MerkleTrie(keyValueStore); Assert.Equal(MerkleTrie.EmptyRootHash, trie.Hash); var committedTrie = trie.Commit(); Assert.Equal(MerkleTrie.EmptyRootHash, committedTrie.Hash); trie = trie.Set(default(Address).ToByteArray(), Dictionary.Empty); committedTrie = trie.Commit(); Assert.NotEqual(MerkleTrie.EmptyRootHash, committedTrie.Hash); }
public void Diff( [Argument( Name = "KV-STORE", Description = KVStoreArgumentDescription)] string kvStoreUri, [Argument( Name = "STATE-ROOT-HASH", Description = "The state root hash to compare.")] string stateRootHashHex, [Argument( Name = "OTHER-KV-STORE", Description = KVStoreArgumentDescription)] string otherKvStoreUri, [Argument( Name = "OTHER-STATE-ROOT-HASH", Description = "Another state root hash to compare.")] string otherStateRootHashHex, [FromService] IConfigurationService <ToolConfiguration> configurationService) { ToolConfiguration toolConfiguration = configurationService.Load(); kvStoreUri = ConvertKVStoreUri(kvStoreUri, toolConfiguration); otherKvStoreUri = ConvertKVStoreUri(otherKvStoreUri, toolConfiguration); IKeyValueStore keyValueStore = LoadKVStoreFromURI(kvStoreUri); IKeyValueStore otherKeyValueStore = LoadKVStoreFromURI(otherKvStoreUri); var trie = new MerkleTrie( keyValueStore, HashDigest <SHA256> .FromString(stateRootHashHex)); var otherTrie = new MerkleTrie( otherKeyValueStore, HashDigest <SHA256> .FromString(otherStateRootHashHex)); foreach (var group in trie.DifferentNodes(otherTrie)) { Console.Error.Write("Path: "); Console.WriteLine(Encoding.UTF8.GetString(ByteUtil.ParseHex(group.Key))); var values = group.ToArray(); foreach (var pair in values) { Console.Error.Write("At "); Console.WriteLine(ByteUtil.Hex(pair.Root.ToByteArray())); Console.WriteLine(pair.Value.Inspection); } Console.WriteLine(); } }
public void DifferentNodes() { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); MerkleTrie trieA = new MerkleTrie(keyValueStore), trieB = new MerkleTrie(keyValueStore); trieA = (MerkleTrie)trieA.Set(new byte[] { 0x01, }, default(Null)) .Set(new byte[] { 0x02, }, default(Null)) .Set(new byte[] { 0x03, }, default(Null)) .Commit(); trieB = (MerkleTrie)trieB.Set(new byte[] { 0x01, }, Dictionary.Empty) .Set(new byte[] { 0x02, }, default(Null)) .Set(new byte[] { 0x04, }, default(Null)) .Commit(); Dictionary <string, (HashDigest <SHA256> Root, IValue Value)[]> differentNodes =
public void IterateNodes() { var merkleTrie = new MerkleTrie(new MemoryKeyValueStore()); // There is nothing. Assert.Empty(merkleTrie.IterateNodes()); merkleTrie = (MerkleTrie)merkleTrie.Set( new byte[] { 0xbe, 0xef, }, Dictionary.Empty.Add(TestUtils.GetRandomBytes(32), default(Null))); // There are (ShortNode, ValueNode) Assert.Equal(2, merkleTrie.IterateNodes().Count()); merkleTrie = (MerkleTrie)merkleTrie.Commit(); // There are (HashNode, ShortNode, HashNode, ValueNode) Assert.Equal(4, merkleTrie.IterateNodes().Count()); }
public void IterateNodes() { var merkleTrie = new MerkleTrie(new MemoryKeyValueStore()); // There is nothing. Assert.Empty(merkleTrie.IterateNodes()); merkleTrie = (MerkleTrie)merkleTrie.Set( new KeyBytes(0xbe, 0xef), Dictionary.Empty.Add(GetRandomBytes(32), Null.Value)); // There are (ShortNode, ValueNode) Assert.Equal(2, merkleTrie.IterateNodes().Count()); merkleTrie = (MerkleTrie)merkleTrie.Commit(); // There are (HashNode, ShortNode, HashNode, ValueNode) Assert.Equal(4, merkleTrie.IterateNodes().Count()); }
public static Block <T> MineGenesis <T>( Address?miner = null, IEnumerable <Transaction <T> > transactions = null, DateTimeOffset?timestamp = null, IAction blockAction = null, bool checkStateRootHash = false ) where T : IAction, new() { if (transactions is null) { transactions = new List <Transaction <T> >(); } var block = new Block <T>( index: 0, difficulty: 0, totalDifficulty: 0, nonce: new Nonce(new byte[] { 0x01, 0x00, 0x00, 0x00 }), miner: miner ?? GenesisMinerAddress, previousHash: null, timestamp: timestamp ?? new DateTimeOffset(2018, 11, 29, 0, 0, 0, TimeSpan.Zero), transactions: transactions ); if (checkStateRootHash) { var blockEvaluator = new BlockEvaluator <T>( blockAction, (address, digest, arg3) => null, (address, currency, arg3, arg4) => new FungibleAssetValue(currency)); var actionEvaluationResult = blockEvaluator .EvaluateActions(block, StateCompleterSet <T> .Reject) .GetTotalDelta(BlockChain <T> .ToStateKey, BlockChain <T> .ToFungibleAssetKey); var trie = new MerkleTrie(new DefaultKeyValueStore(null)); foreach (var pair in actionEvaluationResult) { trie.Set(Encoding.UTF8.GetBytes(pair.Key), pair.Value); } var stateRootHash = trie.Commit(rehearsal: true).Hash; block = new Block <T>(block, stateRootHash); } return(block); }
public void Commit(int addressCount) { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); var codec = new Codec(); ITrie trieA = new MerkleTrie(keyValueStore); var addresses = new Address[addressCount]; var states = new IValue[addressCount]; for (int i = 0; i < addressCount; ++i) { addresses[i] = new PrivateKey().ToAddress(); states[i] = (Binary)TestUtils.GetRandomBytes(128); trieA = trieA.Set(addresses[i].ToByteArray(), states[i]); } byte[] path = TestUtils.GetRandomBytes(32); trieA = trieA.Set(path, (Text)"foo"); HashDigest <SHA256> rootHash = trieA.Hash; Assert.True(trieA.TryGet(path, out IValue stateA)); Assert.Equal((Text)"foo", stateA); ITrie trieB = trieA.Commit(); Assert.True(trieB.TryGet(path, out IValue stateB)); Assert.Equal((Text)"foo", stateB); trieB = trieB.Set(path, (Text)"bar"); Assert.True(trieA.TryGet(path, out stateA)); Assert.Equal((Text)"foo", stateA); Assert.True(trieB.TryGet(path, out stateB)); Assert.Equal((Text)"bar", stateB); ITrie trieC = trieB.Commit(); ITrie trieD = trieC.Commit(); Assert.NotEqual(trieA.Hash, trieB.Hash); Assert.NotEqual(trieA.Hash, trieC.Hash); Assert.NotEqual(trieB.Hash, trieC.Hash); Assert.Equal(trieC.Hash, trieD.Hash); }
public void Diff( [Argument( Name = "KV-STORE", Description = KVStoreArgumentDescription)] string kvStoreUri, [Argument( Name = "STATE-ROOT-HASH", Description = "The state root hash to compare.")] string stateRootHashHex, [Argument( Name = "OTHER-KV-STORE", Description = KVStoreArgumentDescription)] string otherKvStoreUri, [Argument( Name = "OTHER-STATE-ROOT-HASH", Description = "Another state root hash to compare.")] string otherStateRootHashHex, [FromService] IConfigurationService <ToolConfiguration> configurationService) { ToolConfiguration toolConfiguration = configurationService.Load(); kvStoreUri = ConvertKVStoreUri(kvStoreUri, toolConfiguration); otherKvStoreUri = ConvertKVStoreUri(otherKvStoreUri, toolConfiguration); IKeyValueStore keyValueStore = LoadKVStoreFromURI(kvStoreUri); IKeyValueStore otherKeyValueStore = LoadKVStoreFromURI(otherKvStoreUri); var trie = new MerkleTrie( keyValueStore, HashDigest <SHA256> .FromString(stateRootHashHex)); var otherTrie = new MerkleTrie( otherKeyValueStore, HashDigest <SHA256> .FromString(otherStateRootHashHex)); var codec = new Codec(); HashDigest <SHA256> originRootHash = trie.Hash; HashDigest <SHA256> otherRootHash = otherTrie.Hash; string originRootHashHex = ByteUtil.Hex(originRootHash.ByteArray); string otherRootHashHex = ByteUtil.Hex(otherRootHash.ByteArray); foreach (var(key, originValue, otherValue) in trie.DifferentNodes(otherTrie)) { var data = new DiffData(ByteUtil.Hex(key.ByteArray), new Dictionary <string, string> {
public void Diff( [Argument( Name = "KV-STORE", Description = KVStoreArgumentDescription)] string kvStoreUri, [Argument( Name = "STATE-ROOT-HASH", Description = "The state root hash to compare.")] string stateRootHashHex, [Argument( Name = "OTHER-KV-STORE", Description = KVStoreArgumentDescription)] string otherKvStoreUri, [Argument( Name = "OTHER-STATE-ROOT-HASH", Description = "Another state root hash to compare.")] string otherStateRootHashHex, [FromService] IConfigurationService <ToolConfiguration> configurationService) { ToolConfiguration toolConfiguration = configurationService.Load(); kvStoreUri = ConvertKVStoreUri(kvStoreUri, toolConfiguration); otherKvStoreUri = ConvertKVStoreUri(otherKvStoreUri, toolConfiguration); IKeyValueStore keyValueStore = LoadKVStoreFromURI(kvStoreUri); IKeyValueStore otherKeyValueStore = LoadKVStoreFromURI(otherKvStoreUri); var trie = new MerkleTrie( keyValueStore, HashDigest <SHA256> .FromString(stateRootHashHex)); var otherTrie = new MerkleTrie( otherKeyValueStore, HashDigest <SHA256> .FromString(otherStateRootHashHex)); var codec = new Codec(); Dictionary <string, Dictionary <string, string> > dictionary = trie.DifferentNodes(otherTrie).ToDictionary( group => group.Key, group => group.ToDictionary( pair => ByteUtil.Hex(pair.Root.ByteArray), pair => ByteUtil.Hex(codec.Encode(pair.Value)))); Console.Write(JsonSerializer.Serialize(dictionary)); }
public void Commit(int addressCount) { IKeyValueStore keyValueStore = new MemoryKeyValueStore(); var codec = new Codec(); ITrie trieA = new MerkleTrie(keyValueStore); var addresses = new Address[addressCount]; var states = new IValue[addressCount]; for (int i = 0; i < addressCount; ++i) { addresses[i] = new PrivateKey().ToAddress(); states[i] = (Binary)TestUtils.GetRandomBytes(128); trieA = trieA.Set(new KeyBytes(addresses[i].ByteArray), states[i]); } KeyBytes path = new KeyBytes(TestUtils.GetRandomBytes(32)); trieA = trieA.Set(path, (Text)"foo"); Assert.Equal((Text)"foo", trieA.Get(new[] { path })[0]); ITrie trieB = trieA.Commit(); Assert.Equal((Text)"foo", trieB.Get(new[] { path })[0]); trieB = trieB.Set(path, (Text)"bar"); Assert.Equal((Text)"foo", trieA.Get(new[] { path })[0]); Assert.Equal((Text)"bar", trieB.Get(new[] { path })[0]); ITrie trieC = trieB.Commit(); ITrie trieD = trieC.Commit(); Assert.NotEqual(trieA.Hash, trieB.Hash); Assert.NotEqual(trieA.Hash, trieC.Hash); Assert.NotEqual(trieB.Hash, trieC.Hash); Assert.Equal(trieC.Hash, trieD.Hash); }
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(); }
public void Set(bool commit) { ITrie trie = new MerkleTrie(new MemoryKeyValueStore()); AssertBytesEqual( FromString("1b16b1df538ba12dc3f97edbb85caa7050d46c148134290feba80f8236c83db9"), trie.Hash ); Assert.Null(trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); trie = trie.Set(new KeyBytes(0xbe, 0xef), Null.Value); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString("16fc25f43edd0c2d2cb6e3cc3827576e57f4b9e04f8dc3a062c7fe59041f77bd"), trie.Hash ); AssertBencodexEqual(Null.Value, trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); trie = trie.Set(new KeyBytes(0xbe, 0xef), new Boolean(true)); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString("4458796f4092b5ebfc1ffb3989e72edee228501e438080a12dea45591dc66d58"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); Assert.Null(trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); trie = trie.Set(new KeyBytes(0x11, 0x22), List.Empty); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString("ab1359a2497453110a9c658dd3db45f282404fe68d8c8aca30856f395572284c"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); AssertBencodexEqual(List.Empty, trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); trie = trie.Set(new KeyBytes(0xaa, 0xbb), new Text("hello world")); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString("abb5759141f7af1c40f1b0993ba60073cf4227900617be9641373e5a097eaa3c"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); AssertBencodexEqual(List.Empty, trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); AssertBencodexEqual( new Text("hello world"), trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0] ); Assert.Null(trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); var longText = new Text(string.Join("\n", Range(0, 1000).Select(i => $"long str {i}"))); trie = trie.Set(new KeyBytes(0xaa, 0xbb), longText); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString(commit ? "56e5a39a726acba1f7631a6520ae92e20bb93ca3992a7b7d3542c6daee68e56d" : "ad9fb53a8f643bd308d7afea57a5d1796d6031b1df95bdd415fa69b44177d155"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); AssertBencodexEqual(List.Empty, trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); AssertBencodexEqual(longText, trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); Assert.Null(trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); trie = trie.Set(new KeyBytes(0x12, 0x34), Dictionary.Empty); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString(commit ? "88d6375097fd03e6c30a129eb0030d938caeaa796643971ca938fbd27ff5e057" : "77d13e9d97033400ad31fcb0441819285b9165f6ea6ae599d85e7d7e24428feb"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); AssertBencodexEqual(List.Empty, trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); AssertBencodexEqual(longText, trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); AssertBencodexEqual(Dictionary.Empty, trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); List complexList = List.Empty .Add("Hello world") .Add(Dictionary.Empty .Add("foo", 1) .Add("bar", 2) .Add( "lst", Range(0, 1000).Select(i => (IValue) new Text($"long str {i}")))) .Add(new List(Range(0, 1000).Select(i => (IValue) new Text($"long str {i}")))); trie = trie.Set(new KeyBytes(0x11, 0x22), complexList); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString(commit ? "f29820df65c1d1a66b69a59b9fe3e21911bbd2d97a9f298853c529804bf84a26" : "586ba0ba5dfe07433b01fbf7611f95832bde07b8dc5669540ef8866f465bbb85"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); AssertBencodexEqual(complexList, trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); AssertBencodexEqual(longText, trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); AssertBencodexEqual(Dictionary.Empty, trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); Dictionary complexDict = Dictionary.Empty .Add("foo", 123) .Add("bar", 456) .Add("lst", Range(0, 1000).Select(i => (IValue) new Text($"long str {i}"))) .Add("cls", (IValue)complexList) .Add( "dct", Dictionary.Empty .Add("abcd", Null.Value) .Add("efgh", false) .Add("ijkl", true) .Add("mnop", (IValue) new Binary("hello world", Encoding.ASCII)) .Add("qrst", (IValue)complexList) .Add("uvwx", Dictionary.Empty)); trie = trie.Set(new KeyBytes(0x12, 0x34), complexDict); trie = commit ? trie.Commit() : trie; AssertBytesEqual( FromString(commit ? "1dabec2c0fea02af0182e9fee6c7ce7ad1a9d9bcfaa2cd80c2971bbce5272655" : "4783d18dfc8a2d4d98f722a935e45bd7fc1d0197fb4d33e62f734bfde968af39"), trie.Hash ); AssertBencodexEqual( new Boolean(true), trie.Get(new[] { new KeyBytes(0xbe, 0xef) })[0] ); AssertBencodexEqual(complexList, trie.Get(new[] { new KeyBytes(0x11, 0x22) })[0]); AssertBencodexEqual(longText, trie.Get(new[] { new KeyBytes(0xaa, 0xbb) })[0]); AssertBencodexEqual(complexDict, trie.Get(new[] { new KeyBytes(0x12, 0x34) })[0]); }