Пример #1
0
        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));
        }
Пример #2
0
        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);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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));
        }
Пример #5
0
        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));
        }
Пример #6
0
        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));
        }
Пример #7
0
        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));
        }
Пример #8
0
        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));
        }
Пример #9
0
        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));
        }
Пример #10
0
        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));
        }
Пример #11
0
        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));
        }
Пример #12
0
        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));
        }
Пример #13
0
        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));
        }
Пример #14
0
        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}");
                }
            }
        }
Пример #16
0
        // [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 });
                }
            }
        }