Exemple #1
0
        public void Can_sign_on_networks_with_chain_id(DevWalletType walletType)
        {
            const int     networkId = 40000;
            EthereumEcdsa ecdsa     = new EthereumEcdsa(new CustomSpecProvider(networkId, (0, MuirGlacier.Instance)), LimboLogs.Instance);
            IWallet       wallet    = SetupWallet(walletType);

            for (int i = 1; i <= (walletType == DevWalletType.Memory ? 10 : 3); i++)
            {
                Address     signerAddress = wallet.GetAccounts()[0];
                Transaction tx            = new Transaction();
                tx.SenderAddress = signerAddress;

                wallet.Sign(tx, networkId);
                Address recovered = ecdsa.RecoverAddress(tx, networkId);
                Assert.AreEqual(signerAddress, recovered, $"{i}");
                Assert.AreEqual(networkId, tx.Signature.ChainId, "chainId");
            }
        }
Exemple #2
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);
        }
Exemple #3
0
        protected async Task <EthereumTestResult> RunTest(BlockchainTest test, Stopwatch?stopwatch = null)
        {
            TestContext.Write($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}");
            Assert.IsNull(test.LoadFailure, "test data loading failure");

            IDb stateDb = new MemDb();
            IDb codeDb  = new MemDb();

            ISpecProvider specProvider;

            if (test.NetworkAfterTransition != null)
            {
                specProvider = new CustomSpecProvider(1,
                                                      (0, Frontier.Instance),
                                                      (1, test.Network),
                                                      (test.TransitionBlockNumber, test.NetworkAfterTransition));
            }
            else
            {
                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.Network));
            }

            if (specProvider.GenesisSpec != Frontier.Instance)
            {
                Assert.Fail("Expected genesis spec to be Frontier for blockchain tests");
            }

            DifficultyCalculator.Wrapped = new DifficultyCalculator(specProvider);
            IRewardCalculator rewardCalculator = new RewardCalculator(specProvider);

            IEthereumEcdsa ecdsa = new EthereumEcdsa(specProvider.ChainId, _logManager);

            TrieStore      trieStore     = new(stateDb, _logManager);
            IStateProvider stateProvider = new StateProvider(trieStore, codeDb, _logManager);
            MemDb          blockInfoDb   = new MemDb();
            IBlockTree     blockTree     = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, _logManager);
            ITransactionComparerProvider transactionComparerProvider = new TransactionComparerProvider(specProvider, blockTree);
            ITxPool transactionPool = new TxPool(NullTxStorage.Instance, ecdsa, new ChainHeadInfoProvider(specProvider, blockTree, stateProvider), new TxPoolConfig(), new TxValidator(specProvider.ChainId), _logManager, transactionComparerProvider.GetDefaultComparer());

            IReceiptStorage    receiptStorage    = NullReceiptStorage.Instance;
            IBlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, _logManager);
            ITxValidator       txValidator       = new TxValidator(ChainId.Mainnet);
            IHeaderValidator   headerValidator   = new HeaderValidator(blockTree, Sealer, specProvider, _logManager);
            IOmmersValidator   ommersValidator   = new OmmersValidator(blockTree, headerValidator, _logManager);
            IBlockValidator    blockValidator    = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, _logManager);
            IStorageProvider   storageProvider   = new StorageProvider(trieStore, stateProvider, _logManager);
            IVirtualMachine    virtualMachine    = new VirtualMachine(
                stateProvider,
                storageProvider,
                blockhashProvider,
                specProvider,
                _logManager);

            IBlockProcessor blockProcessor = new BlockProcessor(
                specProvider,
                blockValidator,
                rewardCalculator,
                new TransactionProcessor(
                    specProvider,
                    stateProvider,
                    storageProvider,
                    virtualMachine,
                    _logManager),
                stateProvider,
                storageProvider,
                transactionPool,
                receiptStorage,
                NullWitnessCollector.Instance,
                _logManager);

            IBlockchainProcessor blockchainProcessor = new BlockchainProcessor(
                blockTree,
                blockProcessor,
                new RecoverSignatures(ecdsa, NullTxPool.Instance, specProvider, _logManager),
                _logManager,
                BlockchainProcessor.Options.NoReceipts);

            InitializeTestState(test, stateProvider, storageProvider, specProvider);

            List <(Block Block, string ExpectedException)> correctRlp = new();

            for (int i = 0; i < test.Blocks.Length; i++)
            {
                try
                {
                    TestBlockJson testBlockJson  = test.Blocks[i];
                    var           rlpContext     = Bytes.FromHexString(testBlockJson.Rlp).AsRlpStream();
                    Block         suggestedBlock = Rlp.Decode <Block>(rlpContext);
                    suggestedBlock.Header.SealEngineType = test.SealEngineUsed ? SealEngineType.Ethash : SealEngineType.None;

                    Assert.AreEqual(new Keccak(testBlockJson.BlockHeader.Hash), suggestedBlock.Header.Hash, "hash of the block");
                    for (int ommerIndex = 0; ommerIndex < suggestedBlock.Ommers.Length; ommerIndex++)
                    {
                        Assert.AreEqual(new Keccak(testBlockJson.UncleHeaders[ommerIndex].Hash), suggestedBlock.Ommers[ommerIndex].Hash, "hash of the ommer");
                    }

                    correctRlp.Add((suggestedBlock, testBlockJson.ExpectedException));
                }
                catch (Exception)
                {
                    _logger?.Info($"Invalid RLP ({i})");
                }
            }

            if (correctRlp.Count == 0)
            {
                EthereumTestResult result;
                if (test.GenesisBlockHeader is null)
                {
                    result = new EthereumTestResult(test.Name, "Genesis block header missing in the test spec.");
                }
                else if (!new Keccak(test.GenesisBlockHeader.Hash).Equals(test.LastBlockHash))
                {
                    result = new EthereumTestResult(test.Name, "Genesis hash mismatch");
                }
                else
                {
                    result = new EthereumTestResult(test.Name, null, true);
                }

                return(result);
            }

            if (test.GenesisRlp == null)
            {
                test.GenesisRlp = Rlp.Encode(new Block(JsonToEthereumTest.Convert(test.GenesisBlockHeader)));
            }

            Block genesisBlock = Rlp.Decode <Block>(test.GenesisRlp.Bytes);

            Assert.AreEqual(new Keccak(test.GenesisBlockHeader.Hash), genesisBlock.Header.Hash, "genesis header hash");

            ManualResetEvent genesisProcessed = new(false);

            blockTree.NewHeadBlock += (_, args) =>
            {
                if (args.Block.Number == 0)
                {
                    Assert.AreEqual(genesisBlock.Header.StateRoot, stateProvider.StateRoot, "genesis state root");
                    genesisProcessed.Set();
                }
            };

            blockchainProcessor.Start();
            blockTree.SuggestBlock(genesisBlock);

            genesisProcessed.WaitOne();

            for (int i = 0; i < correctRlp.Count; i++)
            {
                stopwatch?.Start();
                try
                {
                    if (correctRlp[i].ExpectedException != null)
                    {
                        _logger.Info($"Expecting block exception: {correctRlp[i].ExpectedException}");
                    }

                    if (correctRlp[i].Block.Hash == null)
                    {
                        throw new Exception($"null hash in {test.Name} block {i}");
                    }

                    // TODO: mimic the actual behaviour where block goes through validating sync manager?
                    if (!test.SealEngineUsed || blockValidator.ValidateSuggestedBlock(correctRlp[i].Block))
                    {
                        blockTree.SuggestBlock(correctRlp[i].Block);
                    }
                    else
                    {
                        Console.WriteLine("Invalid block");
                    }
                }
                catch (InvalidBlockException)
                {
                }
                catch (Exception ex)
                {
                    _logger?.Info(ex.ToString());
                }
            }

            await blockchainProcessor.StopAsync(true);

            stopwatch?.Stop();

            List <string> differences = RunAssertions(test, blockTree.RetrieveHeadBlock(), storageProvider, stateProvider);

//            if (differences.Any())
//            {
//                BlockTrace blockTrace = blockchainProcessor.TraceBlock(blockTree.BestSuggested.Hash);
//                _logger.Info(new UnforgivingJsonSerializer().Serialize(blockTrace, true));
//            }

            Assert.Zero(differences.Count, "differences");

            return(new EthereumTestResult
                   (
                       test.Name,
                       null,
                       differences.Count == 0
                   ));
        }
 public void When_no_transitions_specified_throws_argument_exception()
 {
     Assert.Throws <ArgumentException>(() => _ = new CustomSpecProvider());
 }
Exemple #5
0
        protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
        {
            TestContext.Write($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}");
            Assert.IsNull(test.LoadFailure, "test data loading failure");

            IDb stateDb = new MemDb();
            IDb codeDb  = new MemDb();

            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");
            }

            TrieStore          trieStore         = new(stateDb, _logManager);
            StateProvider      stateProvider     = new (trieStore, codeDb, _logManager);
            IBlockhashProvider blockhashProvider = new TestBlockhashProvider();
            IStorageProvider   storageProvider   = new StorageProvider(trieStore, stateProvider, _logManager);
            IVirtualMachine    virtualMachine    = new VirtualMachine(
                blockhashProvider,
                specProvider,
                _logManager);

            TransactionProcessor transactionProcessor = new(
                specProvider,
                stateProvider,
                storageProvider,
                virtualMachine,
                _logManager);

            InitializeTestState(test, stateProvider, storageProvider, specProvider);

            BlockHeader header = new(test.PreviousHash, Keccak.OfAnEmptySequenceRlp, test.CurrentCoinbase,
                                     test.CurrentDifficulty, test.CurrentNumber, test.CurrentGasLimit, test.CurrentTimestamp, Array.Empty <byte>());

            header.BaseFeePerGas = test.Fork.IsEip1559Enabled ? test.CurrentBaseFee ?? _defaultBaseFeeForStateTest : UInt256.Zero;
            header.StateRoot     = test.PostHash;
            header.Hash          = header.CalculateHash();
            header.IsPostMerge   = test.CurrentRandom is not null;
            header.MixHash       = test.CurrentRandom;

            Stopwatch stopwatch   = Stopwatch.StartNew();
            var       txValidator = new TxValidator((MainnetSpecProvider.Instance.ChainId));
            var       spec        = specProvider.GetSpec(test.CurrentNumber);

            if (test.Transaction.ChainId == null)
            {
                test.Transaction.ChainId = MainnetSpecProvider.Instance.ChainId;
            }
            bool isValid = txValidator.IsWellFormed(test.Transaction, spec);

            if (isValid)
            {
                transactionProcessor.Execute(test.Transaction, header, txTracer);
            }
            stopwatch.Stop();

            stateProvider.Commit(specProvider.GenesisSpec);
            stateProvider.CommitTree(1);

            // '@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(test.Name, test.ForkName, differences.Count == 0);

            testResult.TimeInMs  = (int)stopwatch.Elapsed.TotalMilliseconds;
            testResult.StateRoot = stateProvider.StateRoot;

//            Assert.Zero(differences.Count, "differences");
            return(testResult);
        }