public void Can_ask_about_root_hash_without_commiting() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(TestItem.AddressA, _account0); tree.UpdateRootHash(); Assert.AreEqual("0x545a417202afcb10925b2afddb70a698710bb1cf4ab32942c42e9f019d564fdc", tree.RootHash.ToString(true)); }
public void Can_ask_about_root_hash_without_when_emptied() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), _account0); tree.UpdateRootHash(); Assert.AreNotEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb0"), _account0); tree.UpdateRootHash(); Assert.AreNotEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb1"), _account0); tree.UpdateRootHash(); Assert.AreNotEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb0"), null); tree.UpdateRootHash(); Assert.AreNotEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb1"), null); tree.UpdateRootHash(); Assert.AreNotEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), null); tree.UpdateRootHash(); Assert.AreEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); tree.Commit(0); Assert.AreEqual(PatriciaTree.EmptyTreeHash, tree.RootHash); }
public void Scenario_traverse_leaf_delete_missing() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), _account0); tree.Set(new Keccak("1111111111111111111111111111111ddddddddddddddddddddddddddddddddd"), null); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x491fbb33aaff22c0a7ff68d5c81ec114dddf89d022ccdee838a0e9d6cd45cab4", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0x491fbb33aaff22c0a7ff68d5c81ec114dddf89d022ccdee838a0e9d6cd45cab4", rootHash.ToString(true)); }
public void Scenario_traverse_leaf_read_matching_leaf() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), _account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), null); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", rootHash.ToString(true)); }
public void Scenario_traverse_leaf_update_new_value() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), _account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), _account1); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0xaa5c248d4b4b8c27a654296a8e0cc51131eb9011d9166fa0fca56a966489e169", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0xaa5c248d4b4b8c27a654296a8e0cc51131eb9011d9166fa0fca56a966489e169", rootHash.ToString(true)); }
public void Scenario_traverse_leaf_update_no_change() { MemDb db = new MemDb(); StateTree tree = new StateTree(db); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), _account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), _account0); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x491fbb33aaff22c0a7ff68d5c81ec114dddf89d022ccdee838a0e9d6cd45cab4", rootHash.ToString(true)); tree.Commit(); Assert.AreEqual("0x491fbb33aaff22c0a7ff68d5c81ec114dddf89d022ccdee838a0e9d6cd45cab4", rootHash.ToString(true)); }
public void Scenario_traverse_leaf_update_with_extension() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111111111111111111111111111"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000000000000000000000000000"), _account1); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x215a4bab4cf2d5ebbaa59c82ae94c9707fcf4cc0ca1fe7e18f918e46db428ef9", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0x215a4bab4cf2d5ebbaa59c82ae94c9707fcf4cc0ca1fe7e18f918e46db428ef9", rootHash.ToString(true)); }
public void Scenario_traverse_extension_new_branching() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), _account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"), _account2); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x543c960143a2a06b685d6b92f0c37000273e616bc23888521e7edf15ad06da46", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0x543c960143a2a06b685d6b92f0c37000273e616bc23888521e7edf15ad06da46", rootHash.ToString(true)); }
public void Scenario_traverse_branch_update_missing() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), _account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"), _account2); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0xc063af0bd3dd88320bc852ff8452049c42fbc06d1a69661567bd427572824cbf", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0xc063af0bd3dd88320bc852ff8452049c42fbc06d1a69661567bd427572824cbf", rootHash.ToString(true)); }
public void Scenario_traverse_branch_delete_missing() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), _account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"), null); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x94a193704e99c219d9a21428eb37d6d2d71b3d2cea80c77ff0e201c0df70a283", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0x94a193704e99c219d9a21428eb37d6d2d71b3d2cea80c77ff0e201c0df70a283", rootHash.ToString(true)); }
public void Scenario_traverse_extension_delete_missing() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), _account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeddddddddddddddddddddddddd"), null); Assert.AreEqual(0, db.ReadsCount); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0xf99f1d3234bad8d63d818db36ff63eefc8916263e654db8b800d3bd03f6339a5", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0xf99f1d3234bad8d63d818db36ff63eefc8916263e654db8b800d3bd03f6339a5", rootHash.ToString(true)); }
public void Scenario_traverse_branch_read_missing() { MemDb db = new MemDb(); StateTree tree = new StateTree(db); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), _account1); Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222")); Assert.Null(account); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x94a193704e99c219d9a21428eb37d6d2d71b3d2cea80c77ff0e201c0df70a283", rootHash.ToString(true)); tree.Commit(); Assert.AreEqual("0x94a193704e99c219d9a21428eb37d6d2d71b3d2cea80c77ff0e201c0df70a283", rootHash.ToString(true)); }
public void Scenario_traverse_extension_create_new_extension() { MemDb db = new MemDb(); StateTree tree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), _account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaab00000000"), _account2); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaab11111111"), _account3); Assert.AreEqual(0, db.ReadsCount); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0x0918112fc898173562441709a2c1cbedb80d1aaecaeadf2f3e9492eeaa568c67", rootHash.ToString(true)); tree.Commit(0); Assert.AreEqual("0x0918112fc898173562441709a2c1cbedb80d1aaecaeadf2f3e9492eeaa568c67", rootHash.ToString(true)); }
public void Scenario_traverse_extension_read_missing() { MemDb db = new MemDb(); StateTree tree = new StateTree(db); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), _account1); Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd")); Assert.Null(account); tree.UpdateRootHash(); Keccak rootHash = tree.RootHash; Assert.AreEqual("0xf99f1d3234bad8d63d818db36ff63eefc8916263e654db8b800d3bd03f6339a5", rootHash.ToString(true)); tree.Commit(); Assert.AreEqual("0xf99f1d3234bad8d63d818db36ff63eefc8916263e654db8b800d3bd03f6339a5", rootHash.ToString(true)); }
public void _Test_storage_failed_case(string historicallyFailingCase) { string[] lines = historicallyFailingCase.Split(Environment.NewLine); int storageCount = lines.Length - 2; IDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, LimboLogs.Instance); StateTree tree = new StateTree(trieStore, LimboLogs.Instance); Address address = new Address(Bytes.FromHexString(lines[0])); int accountIndex = int.Parse(lines[1]); UInt256[] indexes = new UInt256[storageCount]; for (int j = 0; j < storageCount; j++) { indexes[j] = UInt256.Parse(lines[j + 2].Replace("storage: ", string.Empty)); } AddressWithStorage addressWithStorage = new AddressWithStorage(); addressWithStorage.StorageCells = new StorageCell[storageCount]; addressWithStorage.Address = address; StorageTree storageTree = new StorageTree(trieStore, Keccak.EmptyTreeHash, LimboLogs.Instance); for (int j = 0; j < storageCount; j++) { UInt256 index = UInt256.Parse(lines[j + 2].Replace("storage: ", string.Empty)); StorageCell storageCell = new StorageCell(address, index); addressWithStorage.StorageCells[j] = storageCell; byte[] rawKey = new byte[32]; addressWithStorage.StorageCells[j].Index.ToBigEndian(rawKey); TestContext.WriteLine($"Set {Keccak.Compute(rawKey).Bytes.ToHexString()}"); storageTree.Set(addressWithStorage.StorageCells[j].Index, new byte[] { 1 }); storageTree.UpdateRootHash(); storageTree.Commit(0); } Account account = Build.An.Account.WithBalance((UInt256)accountIndex).WithStorageRoot(storageTree.RootHash).TestObject; tree.Set(addressWithStorage.Address, account); tree.UpdateRootHash(); tree.Commit(0); TreeDumper treeDumper = new TreeDumper(); tree.Accept(treeDumper, tree.RootHash, true); TestContext.WriteLine(treeDumper.ToString()); AccountProofCollector collector = new AccountProofCollector(address, indexes); tree.Accept(collector, tree.RootHash, true); AccountProof accountProof = collector.BuildResult(); accountProof.Address.Should().Be(address); accountProof.Balance.Should().Be((UInt256)accountIndex); accountProof.Nonce.Should().Be(0); accountProof.CodeHash.Should().Be(Keccak.OfAnEmptyString); if (accountIndex != 0) { accountProof.StorageRoot.Should().NotBe(Keccak.EmptyTreeHash); } accountProof.StorageProofs.Length.Should().Be(accountIndex); for (int j = 0; j < accountProof.StorageProofs.Length; j++) { TrieNode node = new TrieNode(NodeType.Unknown, accountProof.StorageProofs[j].Proof.Last()); node.ResolveNode(new TrieStore(memDb, NullLogManager.Instance)); if (node.Value.Length != 1) { TestContext.WriteLine($"{j}"); // throw new InvalidDataException($"{j}"); } } }
// [TestCase(4, 16, 4, 4)] public void Fuzz_accounts( int accountsCount, int blocksCount, int uniqueValuesCount, int lookupLimit) { string fileName = Path.GetTempFileName(); //string fileName = "C:\\Temp\\fuzz.txt"; _logger.Info( $"Fuzzing with accounts: {accountsCount}, " + $"blocks {blocksCount}, " + $"values: {uniqueValuesCount}, " + $"lookup: {lookupLimit} into file {fileName}"); using FileStream fileStream = new FileStream(fileName, FileMode.Create); using StreamWriter streamWriter = new StreamWriter(fileStream); Queue <Keccak> rootQueue = new Queue <Keccak>(); MemDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, Prune.WhenCacheReaches(1.MB()), Persist.IfBlockOlderThan(lookupLimit), _logManager); StateTree patriciaTree = new StateTree(trieStore, _logManager); byte[][] accounts = new byte[accountsCount][]; byte[][] randomValues = new byte[uniqueValuesCount][]; for (int i = 0; i < randomValues.Length; i++) { bool isEmptyValue = _random.Next(0, 2) == 0; if (isEmptyValue) { randomValues[i] = Array.Empty <byte>(); } else { randomValues[i] = GenerateRandomAccountRlp(); } } for (int accountIndex = 0; accountIndex < accounts.Length; accountIndex++) { byte[] key = new byte[32]; ((UInt256)accountIndex).ToBigEndian(key); accounts[accountIndex] = key; } for (int blockNumber = 0; blockNumber < blocksCount; blockNumber++) { bool isEmptyBlock = _random.Next(5) == 0; if (!isEmptyBlock) { for (int i = 0; i < Math.Max(1, accountsCount / 8); i++) { int randomAccountIndex = _random.Next(accounts.Length); int randomValueIndex = _random.Next(randomValues.Length); byte[] account = accounts[randomAccountIndex]; byte[] value = randomValues[randomValueIndex]; streamWriter.WriteLine( $"Block {blockNumber} - setting {account.ToHexString()} = {value.ToHexString()}"); patriciaTree.Set(account, value); } } streamWriter.WriteLine( $"Commit block {blockNumber} | empty: {isEmptyBlock}"); patriciaTree.UpdateRootHash(); patriciaTree.Commit(blockNumber); rootQueue.Enqueue(patriciaTree.RootHash); } streamWriter.Flush(); fileStream.Seek(0, SeekOrigin.Begin); streamWriter.WriteLine($"DB size: {memDb.Keys.Count}"); _logger.Info($"DB size: {memDb.Keys.Count}"); int verifiedBlocks = 0; while (rootQueue.TryDequeue(out Keccak currentRoot)) { try { patriciaTree.RootHash = currentRoot; for (int i = 0; i < accounts.Length; i++) { patriciaTree.Get(accounts[i]); } _logger.Info($"Verified positive {verifiedBlocks}"); } catch (Exception ex) { if (verifiedBlocks % lookupLimit == 0) { throw new InvalidDataException(ex.ToString()); } else { _logger.Info($"Verified negative {verifiedBlocks}"); } } verifiedBlocks++; } }
public void Chaotic_test() { const int accountsCount = 100; CryptoRandom random = new CryptoRandom(); List <AddressWithStorage> addressesWithStorage = new List <AddressWithStorage>(); for (int i = 0; i < accountsCount; i++) { AddressWithStorage addressWithStorage = new AddressWithStorage(); addressWithStorage.StorageCells = new StorageCell[i]; byte[] addressBytes = random.GenerateRandomBytes(20); addressWithStorage.Address = new Address(addressBytes); for (int j = 0; j < i; j++) { byte[] storageIndex = random.GenerateRandomBytes(32); UInt256 index = new UInt256(storageIndex); StorageCell storageCell = new StorageCell(addressWithStorage.Address, index); addressWithStorage.StorageCells[j] = storageCell; } addressesWithStorage.Add(addressWithStorage); } IDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, LimboLogs.Instance); StateTree tree = new StateTree(trieStore, LimboLogs.Instance); for (int i = 0; i < accountsCount; i++) { Account account = Build.An.Account.WithBalance((UInt256)i).TestObject; StorageTree storageTree = new StorageTree(trieStore, Keccak.EmptyTreeHash, LimboLogs.Instance); for (int j = 0; j < i; j++) { storageTree.Set(addressesWithStorage[i].StorageCells[j].Index, new byte[1] { 1 }); } storageTree.UpdateRootHash(); storageTree.Commit(0); account = account.WithChangedStorageRoot(storageTree.RootHash); tree.Set(addressesWithStorage[i].Address, account); } tree.UpdateRootHash(); tree.Commit(0); for (int i = 0; i < accountsCount; i++) { AccountProofCollector collector = new AccountProofCollector(addressesWithStorage[i].Address, addressesWithStorage[i].StorageCells.Select(sc => sc.Index).ToArray()); tree.Accept(collector, tree.RootHash, true); AccountProof accountProof = collector.BuildResult(); accountProof.Address.Should().Be(addressesWithStorage[i].Address); accountProof.Balance.Should().Be((UInt256)i); accountProof.Nonce.Should().Be(0); accountProof.CodeHash.Should().Be(Keccak.OfAnEmptyString); if (i != 0) { accountProof.StorageRoot.Should().NotBe(Keccak.EmptyTreeHash); } accountProof.StorageProofs.Length.Should().Be(i); for (int j = 0; j < i; j++) { byte[] indexBytes = new byte[32]; addressesWithStorage[i].StorageCells[j].Index.ToBigEndian(indexBytes.AsSpan()); accountProof.StorageProofs[j].Key.ToHexString().Should().Be(indexBytes.ToHexString(), $"{i} {j}"); TrieNode node = new TrieNode(NodeType.Unknown, accountProof.StorageProofs[j].Proof.Last()); node.ResolveNode(null); // TestContext.Write($"|[{i},{j}]"); if (node.Value.Length != 1) { TestContext.WriteLine(); TestContext.WriteLine(addressesWithStorage[i].Address); TestContext.WriteLine(i); foreach (StorageCell storageCell in addressesWithStorage[i].StorageCells) { TestContext.WriteLine("storage: " + storageCell.Index); } } node.Value.Should().BeEquivalentTo(new byte[] { 1 }); } } }