public void Restore_in_the_middle() { byte[] code = new byte[] { 1 }; StateProvider provider = new StateProvider(new StateDb(new MemDb()), Substitute.For <IDb>(), Logger); provider.CreateAccount(_address1, 1); provider.AddToBalance(_address1, 1, Frontier.Instance); provider.IncrementNonce(_address1); Keccak codeHash = provider.UpdateCode(new byte[] { 1 }); provider.UpdateCodeHash(_address1, codeHash, Frontier.Instance); provider.UpdateStorageRoot(_address1, Hash2); Assert.AreEqual(UInt256.One, provider.GetNonce(_address1)); Assert.AreEqual(UInt256.One + 1, provider.GetBalance(_address1)); Assert.AreEqual(code, provider.GetCode(_address1)); provider.Restore(4); Assert.AreEqual(UInt256.One, provider.GetNonce(_address1)); Assert.AreEqual(UInt256.One + 1, provider.GetBalance(_address1)); Assert.AreEqual(code, provider.GetCode(_address1)); provider.Restore(3); Assert.AreEqual(UInt256.One, provider.GetNonce(_address1)); Assert.AreEqual(UInt256.One + 1, provider.GetBalance(_address1)); Assert.AreEqual(code, provider.GetCode(_address1)); provider.Restore(2); Assert.AreEqual(UInt256.One, provider.GetNonce(_address1)); Assert.AreEqual(UInt256.One + 1, provider.GetBalance(_address1)); Assert.AreEqual(new byte[0], provider.GetCode(_address1)); provider.Restore(1); Assert.AreEqual(UInt256.Zero, provider.GetNonce(_address1)); Assert.AreEqual(UInt256.One + 1, provider.GetBalance(_address1)); Assert.AreEqual(new byte[0], provider.GetCode(_address1)); provider.Restore(0); Assert.AreEqual(UInt256.Zero, provider.GetNonce(_address1)); Assert.AreEqual(UInt256.One, provider.GetBalance(_address1)); Assert.AreEqual(new byte[0], provider.GetCode(_address1)); provider.Restore(-1); Assert.AreEqual(false, provider.AccountExists(_address1)); }
// [TestCase(8, 32, 8, 1543322391)] public void Fuzz_accounts_with_storage( int accountsCount, int blocksCount, int lookupLimit, int?seed) { int usedSeed = seed ?? _random.Next(int.MaxValue); _random = new Random(usedSeed); _logger.Info($"RANDOM SEED {usedSeed}"); string fileName = Path.GetTempFileName(); //string fileName = "C:\\Temp\\fuzz.txt"; _logger.Info( $"Fuzzing with accounts: {accountsCount}, " + $"blocks {blocksCount}, " + $"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); StateProvider stateProvider = new StateProvider(trieStore, new MemDb(), _logManager); StorageProvider storageProvider = new StorageProvider(trieStore, stateProvider, _logManager); Account[] accounts = new Account[accountsCount]; Address[] addresses = new Address[accountsCount]; for (int i = 0; i < accounts.Length; i++) { bool isEmptyValue = _random.Next(0, 2) == 0; if (isEmptyValue) { accounts[i] = Account.TotallyEmpty; } else { accounts[i] = GenerateRandomAccount(); } addresses[i] = TestItem.GetRandomAddress(_random); } 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 randomAddressIndex = _random.Next(addresses.Length); int randomAccountIndex = _random.Next(accounts.Length); Address address = addresses[randomAddressIndex]; Account account = accounts[randomAccountIndex]; if (stateProvider.AccountExists(address)) { Account existing = stateProvider.GetAccount(address); if (existing.Balance != account.Balance) { if (account.Balance > existing.Balance) { stateProvider.AddToBalance( address, account.Balance - existing.Balance, MuirGlacier.Instance); } else { stateProvider.SubtractFromBalance( address, existing.Balance - account.Balance, MuirGlacier.Instance); } stateProvider.IncrementNonce(address); } byte[] storage = new byte[1]; _random.NextBytes(storage); storageProvider.Set(new StorageCell(address, 1), storage); } else if (!account.IsTotallyEmpty) { stateProvider.CreateAccount(address, account.Balance); byte[] storage = new byte[1]; _random.NextBytes(storage); storageProvider.Set(new StorageCell(address, 1), storage); } } } streamWriter.WriteLine( $"Commit block {blockNumber} | empty: {isEmptyBlock}"); storageProvider.Commit(); stateProvider.Commit(MuirGlacier.Instance); storageProvider.CommitTrees(blockNumber); stateProvider.CommitTree(blockNumber); rootQueue.Enqueue(stateProvider.StateRoot); } 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 { stateProvider.StateRoot = currentRoot; for (int i = 0; i < addresses.Length; i++) { Account account = stateProvider.GetAccount(addresses[i]); if (account != null) { for (int j = 0; j < 256; j++) { storageProvider.Get(new StorageCell(addresses[i], (UInt256)j)); } } } _logger.Info($"Verified positive {verifiedBlocks}"); } catch (Exception ex) { if (verifiedBlocks % lookupLimit == 0) { throw new InvalidDataException(ex.ToString()); } else { _logger.Info($"Verified negative {verifiedBlocks} which is ok here"); } } verifiedBlocks++; } }