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));
        }
示例#3
0
        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));
        }
示例#5
0
        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));
        }
示例#7
0
        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);
        }
示例#8
0
        // [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++;
            }
        }