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