示例#1
0
        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());
        }
示例#2
0
        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)));
        }
示例#3
0
        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)]);
        }
示例#4
0
        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 { })
示例#5
0
        /// <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)}()");
        }
示例#6
0
        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();
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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));
        }
示例#9
0
        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);
        }
示例#10
0
        /// <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();
        }
示例#11
0
        public void ThrowArgumentNullExceptionWhenSettingNull()
        {
            IKeyValueStore keyValueStore = new MemoryKeyValueStore();
            ITrie          trie          = new MerkleTrie(keyValueStore);

            Assert.Throws <ArgumentNullException>(
                () => trie.Set(new KeyBytes(0xbe, 0xef), null)
                );
        }
示例#12
0
        public void ThrowArgumentNullExceptionWhenSettingNull()
        {
            IKeyValueStore keyValueStore = new MemoryKeyValueStore();
            ITrie          trie          = new MerkleTrie(keyValueStore);

            Assert.Throws <ArgumentNullException>(() =>
            {
                _ = trie.Set(new byte[] { 0xbe, 0xef }, null);
            });
        }
示例#13
0
        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);
        }
示例#14
0
        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();
        }
示例#15
0
        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);
        }
示例#16
0
        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);
        }
示例#17
0
        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();
            }
        }
示例#18
0
        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 =
示例#19
0
        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());
        }
示例#20
0
        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());
        }
示例#21
0
        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);
        }
示例#22
0
        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);
        }
示例#23
0
        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>
                {
示例#24
0
        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));
        }
示例#25
0
        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);
        }
示例#26
0
        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();
        }
示例#27
0
        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]);
        }