public void When_two_branches_with_two_same_children_change_one_and_change_back_next_block() { MemDb memDb = new(); TrieStore trieStore = new(memDb, Prune.WhenCacheReaches(1.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new(trieStore, _logManager); patriciaTree.Set(_keyA, _longLeaf1); patriciaTree.Set(_keyB, _longLeaf1); patriciaTree.Set(_keyC, _longLeaf1); patriciaTree.Set(_keyD, _longLeaf1); patriciaTree.UpdateRootHash(); patriciaTree.Commit(0); patriciaTree.Set(_keyA, _longLeaf3); patriciaTree.Set(_keyA, _longLeaf1); patriciaTree.UpdateRootHash(); patriciaTree.Commit(1); memDb.Keys.Should().HaveCount(5); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); checkTree.Get(_keyA).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(_keyB).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(_keyC).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(_keyD).Should().BeEquivalentTo(_longLeaf1); }
public void Test_update_many(int i) { MemDb memDb = new(); TrieStore trieStore = new(memDb, new MemoryLimit(128.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new(trieStore, _logManager); for (int j = 0; j < i; j++) { Keccak key = TestItem.Keccaks[j]; byte[] value = GenerateIndexedAccountRlp(j); patriciaTree.Set(key.Bytes, value); } for (int j = 0; j < i; j++) { Keccak key = TestItem.Keccaks[j]; byte[] value = GenerateIndexedAccountRlp(j + 1); patriciaTree.Set(key.Bytes, value); } patriciaTree.Commit(0); patriciaTree.UpdateRootHash(); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); for (int j = 0; j < i; j++) { Keccak key = TestItem.Keccaks[j]; byte[] value = GenerateIndexedAccountRlp(j + 1); checkTree.Get(key.Bytes).Should().BeEquivalentTo(value, $@"{i} {j}"); } }
public int Find(string Name) { if (Name == null) { return(-1); } if (TreeNeedsRebuild) { RebuildTree(); } int Output = 0; if (Nodes != null && Nodes.Count > 0) { H3DPatriciaTreeNode Root; Output = PatriciaTree.Traverse(Name, Nodes, out Root); if (Nodes[Output].Name != Name) { Output = 0; } } return(Output - 1); }
public void Test_add_and_delete_many_next_block(int i) { MemDb memDb = new(); TrieStore trieStore = new(memDb, new MemoryLimit(128.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new(trieStore, _logManager); for (int j = 0; j < i; j++) { Keccak key = TestItem.Keccaks[j]; byte[] value = GenerateIndexedAccountRlp(j); patriciaTree.Set(key.Bytes, value); } patriciaTree.Commit(0); for (int j = 0; j < i; j++) { Keccak key = TestItem.Keccaks[j]; patriciaTree.Set(key.Bytes, Array.Empty <byte>()); } patriciaTree.Commit(1); patriciaTree.UpdateRootHash(); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); for (int j = 0; j < i; j++) { Keccak key = TestItem.Keccaks[j]; checkTree.Get(key.Bytes).Should().BeNull($@"{i} {j}"); } }
private void RunTest(TrieTest test, bool secure) { string permutationDescription = string.Join(Environment.NewLine, test.Input.Select(p => $"{p.Key} -> {p.Value}")); TestContext.WriteLine(Surrounded(permutationDescription)); PatriciaTree patriciaTree = secure ? new SecurePatriciaTree(_db) : new PatriciaTree(_db, Keccak.EmptyTreeHash, false); foreach (KeyValuePair <string, string> keyValuePair in test.Input) { string keyString = keyValuePair.Key; string valueString = keyValuePair.Value; Nibble[] key = keyString.StartsWith("0x") ? Hex.ToNibbles(keyString) : Nibbles.FromBytes(Encoding.ASCII.GetBytes(keyString)); byte[] value = valueString.StartsWith("0x") ? Hex.ToBytes(valueString) : Encoding.ASCII.GetBytes(valueString); TestContext.WriteLine(); TestContext.WriteLine($"Setting {keyString} -> {valueString}"); patriciaTree.Set(key, value); } patriciaTree.UpdateRootHash(); Assert.AreEqual(test.ExpectedRoot, patriciaTree.RootHash.ToString()); }
private static PatriciaTree CreateCheckTree(MemDb memDb, PatriciaTree patriciaTree) { PatriciaTree checkTree = new(memDb); checkTree.RootHash = patriciaTree.RootHash; return(checkTree); }
public void Single_leaf_and_keep_for_multiple_dispatches_then_delete() { MemDb memDb = new(); TrieStore trieStore = new(memDb, Prune.WhenCacheReaches(1.MB()), new ConstantInterval(4), LimboLogs.Instance); PatriciaTree patriciaTree = new(trieStore, _logManager); patriciaTree.Commit(0); patriciaTree.Commit(1); patriciaTree.Commit(2); patriciaTree.Set(_keyA, _longLeaf1); patriciaTree.Commit(3); patriciaTree.Commit(4); patriciaTree.Set(_keyA, Array.Empty <byte>()); patriciaTree.Commit(5); patriciaTree.Set(_keyB, _longLeaf2); patriciaTree.Commit(6); patriciaTree.Commit(7); patriciaTree.Commit(8); patriciaTree.Commit(9); patriciaTree.Commit(10); patriciaTree.Commit(11); patriciaTree.Set(_keyB, Array.Empty <byte>()); patriciaTree.Commit(12); patriciaTree.Commit(13); patriciaTree.UpdateRootHash(); // leaf (root) memDb.Keys.Should().HaveCount(2); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); checkTree.Get(_keyA).Should().BeNull(); checkTree.Get(_keyB).Should().BeNull(); }
public void Two_branches_exactly_same_leaf_then_one_removed() { MemDb memDb = new(); TrieStore trieStore = new( memDb, Prune.WhenCacheReaches(1.MB()), Persist.EveryBlock, LimboLogs.Instance); PatriciaTree patriciaTree = new(trieStore, _logManager); patriciaTree.Set(_keyA, _longLeaf1); patriciaTree.Set(_keyB, _longLeaf1); patriciaTree.Set(_keyC, _longLeaf1); patriciaTree.Set(_keyD, _longLeaf1); patriciaTree.Set(_keyA, Array.Empty <byte>()); patriciaTree.Commit(0); // leaf (root) memDb.Keys.Should().HaveCount(6); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); checkTree.Get(_keyA).Should().BeNull(); checkTree.Get(_keyB).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(_keyC).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(_keyD).Should().BeEquivalentTo(_longLeaf1); }
public void Extension_branch_extension_and_leaf_then_branch_leaf_leaf() { /* R * E - - - - - - - - - - - - - - - * B B B B B B B B B B B B B B B B * E L - - - - - - - - - - - - - - * E - - - - - - - - - - - - - - - * B B B B B B B B B B B B B B B B * L L - - - - - - - - - - - - - - */ byte[] key1 = Bytes.FromHexString("000000100000000aa"); byte[] key2 = Bytes.FromHexString("000000100000000bb"); byte[] key3 = Bytes.FromHexString("000000200000000cc"); MemDb memDb = new(); TrieStore trieStore = new(memDb, Prune.WhenCacheReaches(1.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new(trieStore, _logManager); patriciaTree.Set(key1, _longLeaf1); patriciaTree.Set(key2, _longLeaf1); patriciaTree.Set(key3, _longLeaf1); patriciaTree.UpdateRootHash(); patriciaTree.Commit(0); memDb.Keys.Should().HaveCount(7); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); checkTree.Get(key1).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(key2).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(key3).Should().BeEquivalentTo(_longLeaf1); }
private void RebuildTree() { var Nodes = new List <DICTEntry>(); // Adapted from SPICA's code if (Entries.Count > 0) { Nodes.Add(new DICTEntry { ReferenceBit = uint.MaxValue }); } else { Nodes.Add(new DICTEntry()); } int MaxLength = 0; foreach (var Value in Entries) { if (MaxLength < Value.Name.Length) { MaxLength = Value.Name.Length; } } foreach (var Value in Entries) { var Node = new DICTEntry { Name = Value.Name, //EntryObject = Value }; PatriciaTree.Insert(Nodes, Node, MaxLength); } // TODO: Bit of a hacky implementation here, but this "should work" // and at least I thankfully get this functionality, courtesy of SPICA // Nodes index 0 will be the root node, the others should line up with // the subsequent entries... RootEntry = Nodes[0]; for (var entryIndex = 0; entryIndex < Entries.Count; entryIndex++) { var node = Nodes[entryIndex + 1]; // +1 because index zero is the root var entry = Entries[entryIndex]; if (node.Name != entry.Name) { throw new InvalidOperationException("RebuildTree: Name mismatch in node"); } entry.ReferenceBit = node.ReferenceBit; entry.LeftNodeIndex = node.LeftNodeIndex; entry.RightNodeIndex = node.RightNodeIndex; } }
public void Lookup_in_empty_tree() { PatriciaTree tree = new PatriciaTree(new MemDb(), Keccak.EmptyTreeHash, false, true); Assert.AreEqual(tree.RootRef, null); tree.Get(new byte[] { 1 }); Assert.AreEqual(tree.RootRef, null); }
public void Delete_on_empty() { PatriciaTree patriciaTree = new PatriciaTree(_db, Keccak.EmptyTreeHash, false, true); patriciaTree.Set(Keccak.Compute("1").Bytes, new byte[0]); patriciaTree.Commit(); Assert.AreEqual(PatriciaTree.EmptyTreeHash, patriciaTree.RootHash); }
private static IPruningContext CopyDb(IPruningContext pruningContext, MemDb trieDb, MemDb clonedDb) { LimboLogs logManager = LimboLogs.Instance; PatriciaTree trie = Build.A.Trie(trieDb).WithAccountsByIndex(0, 100).TestObject; IStateReader stateReader = new StateReader(new TrieStore(trieDb, logManager), new MemDb(), logManager); using CopyTreeVisitor copyTreeVisitor = new(pruningContext, logManager); stateReader.RunTreeVisitor(copyTreeVisitor, trie.RootHash); return(pruningContext); }
public void Delete_missing_resolved_on_branch() { PatriciaTree patriciaTree = new PatriciaTree(_db, Keccak.EmptyTreeHash, false, true); patriciaTree.Set(Keccak.Compute("1123").Bytes, new byte[] { 1 }); patriciaTree.Set(Keccak.Compute("1124").Bytes, new byte[] { 2 }); Keccak rootBefore = patriciaTree.RootHash; patriciaTree.Set(Keccak.Compute("1125").Bytes, new byte[0]); Assert.AreEqual(rootBefore, patriciaTree.RootHash); }
public void Child_and_value_store_encode() { TrieNode node = new TrieNode(NodeType.Branch); node.SetChild(0, new TrieNode(NodeType.Leaf, TestItem.KeccakA)); PatriciaTree tree = BuildATreeFromNode(node); TrieNode decoded = new TrieNode(NodeType.Unknown, node.Keccak); decoded.ResolveNode(tree); decoded.RlpEncode(); }
public void Connect_extension_with_extension() { /* to test this case we need something like this initially */ /* R * E - - - - - - - - - - - - - - - * B B B B B B B B B B B B B B B B * E L - - - - - - - - - - - - - - * E - - - - - - - - - - - - - - - * B B B B B B B B B B B B B B B B * L L - - - - - - - - - - - - - - */ /* then we delete the leaf (marked as X) */ /* R * B B B B B B B B B B B B B B B B * E X - - - - - - - - - - - - - - * E - - - - - - - - - - - - - - - * B B B B B B B B B B B B B B B B * L L - - - - - - - - - - - - - - */ /* and we end up with an extended extension replacing what was previously a top-level branch*/ /* R * E * E * E - - - - - - - - - - - - - - - * B B B B B B B B B B B B B B B B * L L - - - - - - - - - - - - - - */ byte[] key1 = Bytes.FromHexString("000000100000000aa"); byte[] key2 = Bytes.FromHexString("000000100000000bb"); byte[] key3 = Bytes.FromHexString("000000200000000cc"); MemDb memDb = new(); TrieStore trieStore = new(memDb, Prune.WhenCacheReaches(1.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new(trieStore, _logManager); patriciaTree.Set(key1, _longLeaf1); patriciaTree.Set(key2, _longLeaf1); patriciaTree.Set(key3, _longLeaf1); patriciaTree.UpdateRootHash(); patriciaTree.Commit(0); patriciaTree.Set(key3, Array.Empty <byte>()); patriciaTree.UpdateRootHash(); patriciaTree.Commit(1); memDb.Keys.Should().HaveCount(8); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); checkTree.Get(key1).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(key2).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(key3).Should().BeNull(); }
public void Unknown_node_with_missing_data_can_accept_visitor() { ITreeVisitor visitor = Substitute.For <ITreeVisitor>(); TrieVisitContext context = new TrieVisitContext(); PatriciaTree tree = new PatriciaTree(); TrieNode node = new TrieNode(NodeType.Unknown); node.Accept(visitor, tree, context); visitor.Received().VisitMissingNode(node.Keccak, context); }
public void Two_children_store_resolve_encode() { TrieNode node = new TrieNode(NodeType.Branch); node.SetChild(0, new TrieNode(NodeType.Leaf, TestObject.KeccakA)); node.SetChild(1, new TrieNode(NodeType.Leaf, TestObject.KeccakB)); PatriciaTree tree = BuildATreeFromNode(node); TrieNode decoded = new TrieNode(NodeType.Unknown, node.Keccak); decoded.ResolveNode(tree); decoded.RlpEncode(); }
public void Single_leaf() { MemDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, Prune.WhenCacheReaches(1.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new PatriciaTree(trieStore, _logManager); patriciaTree.Set(_keyA, _longLeaf1); patriciaTree.Commit(0); // leaf (root) memDb.Keys.Should().HaveCount(1); }
public void Delete_missing_resolved_on_extension() { PatriciaTree patriciaTree = new PatriciaTree(_db, Keccak.EmptyTreeHash, false, true); patriciaTree.Set(new Nibble[] { 1, 2, 3, 4 }.ToPackedByteArray(), new byte[] { 1 }); patriciaTree.Set(new Nibble[] { 1, 2, 3, 4, 5 }.ToPackedByteArray(), new byte[] { 2 }); patriciaTree.UpdateRootHash(); Keccak rootBefore = patriciaTree.RootHash; patriciaTree.Set(new Nibble[] { 1, 2, 3 }.ToPackedByteArray(), new byte[] { }); patriciaTree.UpdateRootHash(); Assert.AreEqual(rootBefore, patriciaTree.RootHash); }
public void Delete_missing_resolved_on_leaf() { PatriciaTree patriciaTree = new PatriciaTree(_db, Keccak.EmptyTreeHash, false, true); patriciaTree.Set(Keccak.Compute("1234567").Bytes, new byte[] { 1 }); patriciaTree.Set(Keccak.Compute("1234501").Bytes, new byte[] { 2 }); patriciaTree.UpdateRootHash(); Keccak rootBefore = patriciaTree.RootHash; patriciaTree.Set(Keccak.Compute("1234502").Bytes, new byte[0]); patriciaTree.UpdateRootHash(); Assert.AreEqual(rootBefore, patriciaTree.RootHash); }
private static PatriciaTree BuildATreeFromNode(TrieNode node) { TrieNode.AllowBranchValues = true; byte[] rlp = node.RlpEncode(); node.ResolveKey(true); MemDb memDb = new MemDb(); memDb[node.Keccak.Bytes] = rlp; PatriciaTree tree = new PatriciaTree(memDb, node.Keccak, false, true); return(tree); }
private static PatriciaTree BuildATreeFromNode(TrieNode node) { Rlp rlp = node.RlpEncode(); node.ResolveKey(true); MemDb memDb = new MemDb(); memDb[node.Keccak.Bytes] = rlp.Bytes; PatriciaTree tree = new PatriciaTree(memDb, node.Keccak, false); return(tree); }
public void Extension_can_accept_visitors() { ITreeVisitor visitor = Substitute.For <ITreeVisitor>(); TrieVisitContext context = new TrieVisitContext(); PatriciaTree tree = new PatriciaTree(); TrieNode ignore = new TrieNode(NodeType.Unknown); TrieNode node = new TrieNode(NodeType.Extension); node.SetChild(0, ignore); node.Accept(visitor, tree, context); visitor.Received().VisitExtension(node, context); }
public static Keccak CalculateReceiptRoot(this Block block, ISpecProvider specProvider, TxReceipt[] txReceipts) { PatriciaTree receiptTree = txReceipts.Length > 0 ? new PatriciaTree(NullDb.Instance, Keccak.EmptyTreeHash, false) : null; for (int i = 0; i < txReceipts.Length; i++) { Rlp receiptRlp = Rlp.Encode(txReceipts[i], specProvider.GetSpec(block.Number).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None); receiptTree?.Set(Rlp.Encode(i).Bytes, receiptRlp); } receiptTree?.UpdateRootHash(); Keccak receiptRoot = receiptTree?.RootHash ?? PatriciaTree.EmptyTreeHash; return(receiptRoot); }
private void SetReceiptsRootAndBloom(Block block, TransactionReceipt[] transactionReceipts) { PatriciaTree receiptTree = transactionReceipts.Length > 0 ? new PatriciaTree(NullDb.Instance, Keccak.EmptyTreeHash, false) : null; for (int i = 0; i < transactionReceipts.Length; i++) { Rlp receiptRlp = Rlp.Encode(transactionReceipts[i], _specProvider.GetSpec(block.Header.Number).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None); receiptTree?.Set(Rlp.Encode(i).Bytes, receiptRlp); } receiptTree?.UpdateRootHash(); block.Header.ReceiptsRoot = receiptTree?.RootHash ?? PatriciaTree.EmptyTreeHash; block.Header.Bloom = transactionReceipts.Length > 0 ? BuildBloom(transactionReceipts) : Bloom.Empty; }
private void SetReceipts(Block block, TransactionReceipt[] receipts) { PatriciaTree receiptTree = receipts.Length > 0 ? new PatriciaTree(NullDb.Instance, Keccak.EmptyTreeHash, false) : null; for (int i = 0; i < receipts.Length; i++) { Rlp receiptRlp = Rlp.Encode(receipts[i], _specProvider.GetSpec(block.Header.Number).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None); receiptTree?.Set(Rlp.Encode(i).Bytes, receiptRlp); } receiptTree?.UpdateRootHash(); block.Header.ReceiptsRoot = receiptTree?.RootHash ?? PatriciaTree.EmptyTreeHash; block.Header.Bloom = receipts.Length > 0 ? TransactionProcessor.BuildBloom(receipts.SelectMany(r => r.Logs).ToArray()) : Bloom.Empty; // TODO not tested anywhere at the time of writing }
public void Extension_with_branch_with_two_same_children() { MemDb memDb = new(); TrieStore trieStore = new(memDb, Prune.WhenCacheReaches(1.MB()), Persist.EveryBlock, _logManager); PatriciaTree patriciaTree = new(trieStore, _logManager); patriciaTree.Set(_keyA, _longLeaf1); patriciaTree.Set(_keyB, _longLeaf1); patriciaTree.Commit(0); memDb.Keys.Should().HaveCount(4); PatriciaTree checkTree = CreateCheckTree(memDb, patriciaTree); checkTree.Get(_keyA).Should().BeEquivalentTo(_longLeaf1); checkTree.Get(_keyB).Should().BeEquivalentTo(_longLeaf1); }
public void Leaf_with_simple_account_can_accept_visitors() { ITreeVisitor visitor = Substitute.For <ITreeVisitor>(); TrieVisitContext context = new TrieVisitContext(); PatriciaTree tree = new PatriciaTree(); Account account = new Account(100); AccountDecoder decoder = new AccountDecoder(); TrieNode node = new TrieNode(NodeType.Leaf); node.Value = decoder.Encode(account).Bytes; node.Accept(visitor, tree, context); visitor.Received().VisitLeaf(node, context, node.Value); }
public void Leaf_with_contract_without_storage_and_empty_code_can_accept_visitors() { ITreeVisitor visitor = Substitute.For <ITreeVisitor>(); TrieVisitContext context = new TrieVisitContext(); PatriciaTree tree = new PatriciaTree(); Account account = new Account(1, 100, Keccak.EmptyTreeHash, Keccak.OfAnEmptyString); AccountDecoder decoder = new AccountDecoder(); TrieNode node = new TrieNode(NodeType.Leaf); node.Value = decoder.Encode(account).Bytes; node.Accept(visitor, tree, context); visitor.Received().VisitLeaf(node, context, node.Value); }
protected static PatriciaTree Join (PatriciaTree t0, PatriciaTree t1) { int p0 = t0.KeyNumber, p1 = t1.KeyNumber; int m = BranchingBit(p0, p1); return ZeroBit(p0, m) ? new Branch(MaskBits(p0,m), m, t0, t1) : new Branch(MaskBits(p0,m), m, t1, t0); }
public Branch (int prefix, int mask, PatriciaTree left, PatriciaTree right) { this.Prefix = prefix; this.Mask = mask; this.Left = left; this.Right = right; this.count = left.Count + right.Count; }