public void Account_is_not_created_on_call_and_restore() { long gasLimit = 100000; Transaction tx = Build.A.Transaction .WithValue(0.Ether()) .WithGasPrice(1) .WithGasLimit(gasLimit) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyD, _isEip155Enabled) .TestObject; Block block = Build.A.Block.WithNumber(1).WithTransactions(tx).WithGasLimit(gasLimit).TestObject; _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); _transactionProcessor.CallAndRestore(tx, block.Header, NullTxTracer.Instance); _stateProvider.AccountExists(TestItem.PrivateKeyD.Address).Should().BeFalse(); }
public void Eip_158_zero_value_transfer_deletes() { StateTree tree = new StateTree(new MemDb()); StateProvider frontierProvider = new StateProvider(tree, Substitute.For <IDb>(), Logger); frontierProvider.CreateAccount(_address1, 0); frontierProvider.Commit(Frontier.Instance); StateProvider provider = new StateProvider(tree, Substitute.For <IDb>(), Logger); provider.AddToBalance(_address1, 0, SpuriousDragon.Instance); provider.Commit(SpuriousDragon.Instance); Assert.False(provider.AccountExists(_address1)); }
public void Disables_Eip158_for_system_transactions() { _stateProvider.CreateAccount(TestItem.PrivateKeyA.Address, 0.Ether()); _stateProvider.Commit(_specProvider.GetSpec(1)); var blockNumber = MainNetSpecProvider.SpuriousDragonBlockNumber + 1; Transaction tx = Build.A.SystemTransaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, blockNumber) .WithGasPrice(0) .WithValue(0) .TestObject; Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; BlockReceiptsTracer tracer = BuildTracer(block, tx, false, false); Execute(tracer, tx, block); _stateProvider.AccountExists(tx.SenderAddress).Should().BeTrue(); }
public void Touch_empty_trace_does_not_throw() { ParityLikeTxTracer tracer = new ParityLikeTxTracer(Build.A.Block.TestObject, null, ParityTraceTypes.StateDiff); StateProvider provider = new StateProvider(new StateDb(new MemDb()), Substitute.For <IDb>(), Logger); provider.CreateAccount(_address1, 0); Account account = provider.GetAccount(_address1); Assert.True(account.IsEmpty); provider.Commit(Frontier.Instance); // commit empty account (before the empty account fix in Spurious Dragon) Assert.True(provider.AccountExists(_address1)); provider.Reset(); // clear all caches provider.GetBalance(_address1); // justcache provider.AddToBalance(_address1, 0, SpuriousDragon.Instance); // touch Assert.DoesNotThrow(() => provider.Commit(SpuriousDragon.Instance, tracer)); }
public void Eip_158_zero_value_transfer_deletes() { var trieStore = new TrieStore(new MemDb(), Logger); StateProvider frontierProvider = new StateProvider(trieStore, _codeDb, Logger); frontierProvider.CreateAccount(_address1, 0); frontierProvider.Commit(Frontier.Instance); frontierProvider.CommitTree(0); StateProvider provider = new StateProvider(trieStore, _codeDb, Logger); provider.StateRoot = frontierProvider.StateRoot; provider.AddToBalance(_address1, 0, SpuriousDragon.Instance); provider.Commit(SpuriousDragon.Instance); Assert.False(provider.AccountExists(_address1)); _codeDb = Substitute.For <IDb>(); }
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)); }
protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer) { TestContext.Write($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}"); Stopwatch stopwatch = Stopwatch.StartNew(); Assert.IsNull(test.LoadFailure, "test data loading failure"); ISnapshotableDb stateDb = new StateDb(); ISnapshotableDb codeDb = new StateDb(); ISpecProvider specProvider = new CustomSpecProvider(1, (0, Frontier.Instance), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier (1, test.Fork)); if (specProvider.GenesisSpec != Frontier.Instance) { Assert.Fail("Expected genesis spec to be Frontier for blockchain tests"); } IStateProvider stateProvider = new StateProvider(stateDb, codeDb, _logManager); IBlockhashProvider blockhashProvider = new TestBlockhashProvider(); IStorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, _logManager); IVirtualMachine virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, specProvider, _logManager); TransactionProcessor transactionProcessor = new TransactionProcessor( specProvider, stateProvider, storageProvider, virtualMachine, _logManager); InitializeTestState(test, stateProvider, storageProvider, specProvider); BlockHeader header = new BlockHeader(test.PreviousHash, Keccak.OfAnEmptySequenceRlp, test.CurrentCoinbase, test.CurrentDifficulty, test.CurrentNumber, test.CurrentGasLimit, test.CurrentTimestamp, new byte[0]); header.StateRoot = test.PostHash; header.Hash = Keccak.Compute("1"); stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(); transactionProcessor.Execute(test.Transaction, header, txTracer); stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(); // '@winsvega added a 0-wei reward to the miner , so we had to add that into the state test execution phase. He needed it for retesteth.' if (!stateProvider.AccountExists(test.CurrentCoinbase)) { stateProvider.CreateAccount(test.CurrentCoinbase, 0); } stateProvider.RecalculateStateRoot(); List <string> differences = RunAssertions(test, stateProvider); EthereumTestResult testResult = new EthereumTestResult(); testResult.Pass = differences.Count == 0; testResult.Fork = test.ForkName; testResult.Name = test.Name; testResult.TimeInMs = (int)stopwatch.Elapsed.TotalMilliseconds; testResult.StateRoot = stateProvider.StateRoot; // Assert.Zero(differences.Count, "differences"); return(testResult); }
// [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++; } }