public void Can_collect_stats() { MemDb memDb = new MemDb(); IDb stateDb = memDb; TrieStore trieStore = new TrieStore(stateDb, new MemoryLimit(0.MB()), Persist.EveryBlock, LimboLogs.Instance); StateProvider stateProvider = new StateProvider(trieStore, stateDb, LimboLogs.Instance); StorageProvider storageProvider = new StorageProvider(trieStore, stateProvider, LimboLogs.Instance); stateProvider.CreateAccount(TestItem.AddressA, 1); Keccak codeHash = stateProvider.UpdateCode(new byte[] { 1, 2, 3 }); stateProvider.UpdateCodeHash(TestItem.AddressA, codeHash, Istanbul.Instance); stateProvider.CreateAccount(TestItem.AddressB, 1); Keccak codeHash2 = stateProvider.UpdateCode(new byte[] { 1, 2, 3, 4 }); stateProvider.UpdateCodeHash(TestItem.AddressB, codeHash2, Istanbul.Instance); for (int i = 0; i < 1000; i++) { StorageCell storageCell = new StorageCell(TestItem.AddressA, (UInt256)i); storageProvider.Set(storageCell, new byte[] { (byte)i }); } storageProvider.Commit(); stateProvider.Commit(Istanbul.Instance); storageProvider.CommitTrees(0); stateProvider.CommitTree(0); storageProvider.CommitTrees(1); stateProvider.CommitTree(1); memDb.Delete(codeHash2); // missing code Keccak storageKey = new Keccak("0x345e54154080bfa9e8f20c99d7a0139773926479bc59e5b4f830ad94b6425332"); memDb.Delete(storageKey); // deletes some storage trieStore.ClearCache(); TrieStatsCollector statsCollector = new TrieStatsCollector(stateDb, LimboLogs.Instance); stateProvider.Accept(statsCollector, stateProvider.StateRoot); var stats = statsCollector.Stats; stats.CodeCount.Should().Be(1); stats.MissingCode.Should().Be(1); stats.NodesCount.Should().Be(1348); stats.StateBranchCount.Should().Be(1); stats.StateExtensionCount.Should().Be(1); stats.AccountCount.Should().Be(2); stats.StorageCount.Should().Be(1343); stats.StorageBranchCount.Should().Be(337); stats.StorageExtensionCount.Should().Be(12); stats.StorageLeafCount.Should().Be(994); stats.MissingStorage.Should().Be(1); }
public void Throws_on_theoretical_contract_crash() { var contractAddress = Address.OfContract(_senderPublicKey.ToKvmAddress(), 0); _stateProvider.CreateAccount(contractAddress, 1000.Kat()); var codeHash = _stateProvider.UpdateCode(Bytes.FromHexString("0x01")); _stateProvider.UpdateCodeHash(contractAddress, codeHash, _specProvider.GenesisSpec); _stateProvider.Commit(_specProvider.GenesisSpec); var delta = EntryUtils.PrepareSingleContractEntryDelta(null, _senderPublicKey, 0, "0x60016000526001601FF300"); delta.PublicEntries[0].GasLimit = 1_000_000L; delta.PublicEntries[0].ReceiverAddress = ByteString.Empty; delta.PublicEntries[0].Signature = delta.PublicEntries[0] .GenerateSignature(_cryptoContext, _senderPrivateKey, _signingContext); var tracer = Substitute.For <ITxTracer>(); tracer.IsTracingReceipt.Returns(true); _executor.Execute(delta, tracer); tracer.Received().MarkAsFailed(contractAddress, 1_000_000L, Arg.Any <byte[]>(), null); }
private static void InitializeTestState(GeneralStateTest test, StateProvider stateProvider, IStorageProvider storageProvider, ISpecProvider specProvider) { foreach (KeyValuePair <Address, AccountState> accountState in test.Pre) { foreach (KeyValuePair <UInt256, byte[]> storageItem in accountState.Value.Storage) { storageProvider.Set(new StorageCell(accountState.Key, storageItem.Key), storageItem.Value.WithoutLeadingZeros().ToArray()); } stateProvider.CreateAccount(accountState.Key, accountState.Value.Balance); Keccak codeHash = stateProvider.UpdateCode(accountState.Value.Code); stateProvider.UpdateCodeHash(accountState.Key, codeHash, specProvider.GenesisSpec); stateProvider.SetNonce(accountState.Key, accountState.Value.Nonce); } storageProvider.Commit(); stateProvider.Commit(specProvider.GenesisSpec); storageProvider.CommitTrees(0); stateProvider.CommitTree(0); storageProvider.Reset(); stateProvider.Reset(); }
private void AddCode(StateProvider stateProvider, Address account, byte[] code) { Keccak codeHash = stateProvider.UpdateCode(code); stateProvider.UpdateCodeHash(account, codeHash, MuirGlacier.Instance); stateProvider.Commit(MainnetSpecProvider.Instance.GenesisSpec, NullStateTracer.Instance); }
private void AddCode(StateProvider stateProvider, Address account, byte[] code) { Keccak codeHash = stateProvider.UpdateCode(code); stateProvider.UpdateCodeHash(account, codeHash, MuirGlacier.Instance); stateProvider.Commit(MainNetSpecProvider.Instance.GenesisSpec, null); stateProvider.CommitTree(); _dbProvider.CodeDb.Commit(); _dbProvider.StateDb.Commit(); }
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 virtual async Task <TestBlockchain> Build(ISpecProvider specProvider = null, UInt256?initialValues = null) { Timestamper = new ManualTimestamper(new DateTime(2020, 2, 15, 12, 50, 30, DateTimeKind.Utc)); JsonSerializer = new EthereumJsonSerializer(); SpecProvider = specProvider ?? MainnetSpecProvider.Instance; EthereumEcdsa = new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance); ITxStorage txStorage = new InMemoryTxStorage(); DbProvider = await TestMemDbProvider.InitAsync(); State = new StateProvider(StateDb, CodeDb, LimboLogs.Instance); State.CreateAccount(TestItem.AddressA, (initialValues ?? 1000.Ether())); State.CreateAccount(TestItem.AddressB, (initialValues ?? 1000.Ether())); State.CreateAccount(TestItem.AddressC, (initialValues ?? 1000.Ether())); byte[] code = Bytes.FromHexString("0xabcd"); Keccak codeHash = Keccak.Compute(code); State.UpdateCode(code); State.UpdateCodeHash(TestItem.AddressA, codeHash, SpecProvider.GenesisSpec); Storage = new StorageProvider(StateDb, State, LimboLogs.Instance); Storage.Set(new StorageCell(TestItem.AddressA, UInt256.One), Bytes.FromHexString("0xabcdef")); Storage.Commit(); State.Commit(SpecProvider.GenesisSpec); State.CommitTree(); TxPool = new TxPool.TxPool( txStorage, EthereumEcdsa, SpecProvider, new TxPoolConfig(), new StateProvider(StateDb, CodeDb, LimboLogs.Instance), LimboLogs.Instance); IDb blockDb = new MemDb(); IDb headerDb = new MemDb(); IDb blockInfoDb = new MemDb(); BlockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockDb), SpecProvider, NullBloomStorage.Instance, LimboLogs.Instance); new OnChainTxWatcher(BlockTree, TxPool, SpecProvider, LimboLogs.Instance); ReceiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new VirtualMachine(State, Storage, new BlockhashProvider(BlockTree, LimboLogs.Instance), SpecProvider, LimboLogs.Instance); TxProcessor = new TransactionProcessor(SpecProvider, State, Storage, virtualMachine, LimboLogs.Instance); BlockProcessor = CreateBlockProcessor(); BlockchainProcessor chainProcessor = new BlockchainProcessor(BlockTree, BlockProcessor, new RecoverSignatures(EthereumEcdsa, TxPool, SpecProvider, LimboLogs.Instance), LimboLogs.Instance, Nethermind.Blockchain.Processing.BlockchainProcessor.Options.Default); BlockchainProcessor = chainProcessor; chainProcessor.Start(); StateReader = new StateReader(StateDb, CodeDb, LimboLogs.Instance); TxPoolTxSource txPoolTxSource = CreateTxPoolTxSource(); ISealer sealer = new NethDevSealEngine(TestItem.AddressD); BlockProducer = new TestBlockProducer(txPoolTxSource, chainProcessor, State, sealer, BlockTree, chainProcessor, Timestamper, LimboLogs.Instance); BlockProducer.Start(); _resetEvent = new SemaphoreSlim(0); _suggestedBlockResetEvent = new ManualResetEvent(true); BlockTree.NewHeadBlock += (s, e) => { _resetEvent.Release(1); }; BlockProducer.LastProducedBlockChanged += (s, e) => { _suggestedBlockResetEvent.Set(); }; var genesis = GetGenesisBlock(); BlockTree.SuggestBlock(genesis); await _resetEvent.WaitAsync(); //if (!await _resetEvent.WaitAsync(1000)) // { // throw new InvalidOperationException("Failed to process genesis in 1s."); // } await AddBlocksOnStart(); return(this); }
public async Task Can_process_mined_blocks() { int timeMultiplier = 1; // for debugging TimeSpan miningDelay = TimeSpan.FromMilliseconds(50 * timeMultiplier); /* logging & instrumentation */ // OneLoggerLogManager logger = new OneLoggerLogManager(new SimpleConsoleLogger(true)); ILogManager logManager = NullLogManager.Instance; ILogger logger = logManager.GetClassLogger(); /* spec */ FakeSealer sealer = new FakeSealer(miningDelay); RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; /* store & validation */ EthereumEcdsa ecdsa = new EthereumEcdsa(specProvider, logManager); MemDb receiptsDb = new MemDb(); MemDb traceDb = new MemDb(); TxPool txPool = new TxPool(NullTxStorage.Instance, Timestamp.Default, ecdsa, specProvider, new TxPoolConfig(), logManager); IReceiptStorage receiptStorage = new PersistentReceiptStorage(receiptsDb, NullDb.Instance, specProvider, logManager); BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), specProvider, txPool, logManager); Timestamp timestamp = new Timestamp(); DifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); HeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, logManager); OmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, logManager); TxValidator txValidator = new TxValidator(ChainId.Ropsten); BlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); /* state & storage */ StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); StateProvider stateProvider = new StateProvider(stateDb, codeDb, logManager); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, logManager); TestTransactionsGenerator generator = new TestTransactionsGenerator(txPool, ecdsa, TimeSpan.FromMilliseconds(5 * timeMultiplier), NullLogManager.Instance); generator.Start(); /* blockchain processing */ BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, logManager); TransactionProcessor processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); RewardCalculator rewardCalculator = new RewardCalculator(specProvider); BlockProcessor blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, traceDb, stateProvider, storageProvider, txPool, receiptStorage, logManager); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ecdsa, NullTxPool.Instance, LimboLogs.Instance), logManager, false, false); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = "chainspec.json"; logManager.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); foreach (var allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value.Balance); if (allocation.Value.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Value.Code); stateProvider.UpdateCodeHash(allocation.Key, codeHash, specProvider.GenesisSpec); } } stateProvider.Commit(specProvider.GenesisSpec); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; // TODO: shall it be HeaderSpec and not BlockHeader? chainSpec.Genesis.Header.Hash = BlockHeader.CalculateHash(chainSpec.Genesis.Header); if (chainSpec.Genesis.Hash != new Keccak("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")) { throw new Exception("Unexpected genesis hash"); } /* start processing */ blockTree.SuggestBlock(chainSpec.Genesis); blockchainProcessor.Start(); MinedBlockProducer minedBlockProducer = new MinedBlockProducer(difficultyCalculator, txPool, blockchainProcessor, sealer, blockTree, timestamp, NullLogManager.Instance); minedBlockProducer.Start(); ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.Wait(miningDelay * 12 * timeMultiplier); await minedBlockProducer.StopAsync(); int previousCount = 0; int totalTx = 0; for (int i = 0; i < 6; i++) { Block block = blockTree.FindBlock(i); logger.Info($"Block {i} with {block.Transactions.Length} txs"); ManualResetEventSlim blockProcessedEvent = new ManualResetEventSlim(false); blockchainProcessor.ProcessingQueueEmpty += (sender, args) => blockProcessedEvent.Set(); blockchainProcessor.SuggestBlock(block, ProcessingOptions.ForceProcessing | ProcessingOptions.StoreReceipts | ProcessingOptions.ReadOnlyChain); blockProcessedEvent.Wait(1000); Tracer tracer = new Tracer(blockchainProcessor, receiptStorage, blockTree, new MemDb()); int currentCount = receiptsDb.Keys.Count; logger.Info($"Current count of receipts {currentCount}"); logger.Info($"Previous count of receipts {previousCount}"); if (block.Transactions.Length > 0) { GethLikeTxTrace trace = tracer.Trace(block.Transactions[0].Hash); Assert.AreSame(GethLikeTxTrace.QuickFail, trace); Assert.AreNotEqual(previousCount, currentCount, $"receipts at block {i}"); totalTx += block.Transactions.Length; } previousCount = currentCount; } Assert.AreNotEqual(0, totalTx, "no tx in blocks"); }
// It takes dotCover to run it quite long, increased timeouts public async Task Can_process_mined_blocks() { int timeMultiplier = 1; // for debugging TimeSpan miningDelay = TimeSpan.FromMilliseconds(200 * timeMultiplier); /* logging & instrumentation */ // OneLoggerLogManager logger = new OneLoggerLogManager(new SimpleConsoleLogger(true)); ILogManager logManager = LimboLogs.Instance; ILogger logger = logManager.GetClassLogger(); /* spec */ FakeSealer sealer = new FakeSealer(miningDelay); RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; /* state & storage */ StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); StateProvider stateProvider = new StateProvider(stateDb, codeDb, logManager); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, logManager); /* store & validation */ EthereumEcdsa ecdsa = new EthereumEcdsa(specProvider, logManager); MemDb receiptsDb = new MemDb(); TxPool.TxPool txPool = new TxPool.TxPool(NullTxStorage.Instance, Timestamper.Default, ecdsa, specProvider, new TxPoolConfig(), stateProvider, logManager); IReceiptStorage receiptStorage = new PersistentReceiptStorage(receiptsDb, specProvider, logManager); var blockInfoDb = new MemDb(); BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, txPool, NullBloomStorage.Instance, logManager); Timestamper timestamper = new Timestamper(); DifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); HeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, logManager); OmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, logManager); TxValidator txValidator = new TxValidator(ChainId.Ropsten); BlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); TestTransactionsGenerator generator = new TestTransactionsGenerator(txPool, ecdsa, TimeSpan.FromMilliseconds(50 * timeMultiplier), LimboLogs.Instance); generator.Start(); /* blockchain processing */ BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, specProvider, logManager); TransactionProcessor processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); RewardCalculator rewardCalculator = new RewardCalculator(specProvider); BlockProcessor blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, stateProvider, storageProvider, txPool, receiptStorage, logManager); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ecdsa, NullTxPool.Instance, LimboLogs.Instance), logManager, false); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = "chainspec.json"; logManager.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); foreach (var allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value.Balance); if (allocation.Value.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Value.Code); stateProvider.UpdateCodeHash(allocation.Key, codeHash, specProvider.GenesisSpec); } } stateProvider.Commit(specProvider.GenesisSpec); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; chainSpec.Genesis.Header.Hash = chainSpec.Genesis.Header.CalculateHash(); if (chainSpec.Genesis.Hash != new Keccak("0xafbc3c327d2d18ff2b843e89226ef288fcee379542f854f982e4cfb85916d126")) { throw new Exception("Unexpected genesis hash"); } /* start processing */ blockTree.SuggestBlock(chainSpec.Genesis); blockchainProcessor.Start(); var transactionSelector = new PendingTxSelector(txPool, stateProvider, logManager); MinedBlockProducer minedBlockProducer = new MinedBlockProducer(transactionSelector, blockchainProcessor, sealer, blockTree, blockchainProcessor, stateProvider, timestamper, LimboLogs.Instance, difficultyCalculator); minedBlockProducer.Start(); ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.Wait(miningDelay * 100); await minedBlockProducer.StopAsync(); int previousCount = 0; int totalTx = 0; for (int i = 0; i < 6; i++) { Block block = blockTree.FindBlock(i, BlockTreeLookupOptions.None); Assert.That(block, Is.Not.Null, $"Block {i} not produced"); logger.Info($"Block {i} with {block.Transactions.Length} txs"); ManualResetEventSlim blockProcessedEvent = new ManualResetEventSlim(false); blockchainProcessor.ProcessingQueueEmpty += (sender, args) => blockProcessedEvent.Set(); blockchainProcessor.Enqueue(block, ProcessingOptions.ForceProcessing | ProcessingOptions.StoreReceipts | ProcessingOptions.ReadOnlyChain); blockProcessedEvent.Wait(miningDelay); GethStyleTracer gethStyleTracer = new GethStyleTracer(blockchainProcessor, receiptStorage, blockTree); int currentCount = receiptsDb.Keys.Count; logger.Info($"Current count of receipts {currentCount}"); logger.Info($"Previous count of receipts {previousCount}"); if (block.Transactions.Length > 0) { Assert.AreNotEqual(previousCount, currentCount, $"receipts at block {i}"); totalTx += block.Transactions.Length; } previousCount = currentCount; } Assert.AreNotEqual(0, totalTx, "no tx in blocks"); }
private void Initialize(bool auRa = false) { ISpecProvider specProvider = MainnetSpecProvider.Instance; IEthereumEcdsa ethereumEcdsa = new EthereumEcdsa(specProvider, LimboLogs.Instance); ITxStorage txStorage = new InMemoryTxStorage(); _stateDb = new StateDb(); ISnapshotableDb codeDb = new StateDb(); IStateReader stateReader = new StateReader(_stateDb, codeDb, LimboLogs.Instance); _stateProvider = new StateProvider(_stateDb, codeDb, LimboLogs.Instance); _stateProvider.CreateAccount(TestItem.AddressA, 1000.Ether()); _stateProvider.CreateAccount(TestItem.AddressB, 1000.Ether()); _stateProvider.CreateAccount(TestItem.AddressC, 1000.Ether()); byte[] code = Bytes.FromHexString("0xabcd"); Keccak codeHash = Keccak.Compute(code); _stateProvider.UpdateCode(code); _stateProvider.UpdateCodeHash(TestItem.AddressA, codeHash, specProvider.GenesisSpec); IStorageProvider storageProvider = new StorageProvider(_stateDb, _stateProvider, LimboLogs.Instance); storageProvider.Set(new StorageCell(TestItem.AddressA, UInt256.One), Bytes.FromHexString("0xabcdef")); storageProvider.Commit(); _stateProvider.Commit(specProvider.GenesisSpec); _stateProvider.CommitTree(); ITxPool txPool = new TxPool.TxPool(txStorage, Timestamper.Default, ethereumEcdsa, specProvider, new TxPoolConfig(), _stateProvider, LimboLogs.Instance); IDb blockDb = new MemDb(); IDb headerDb = new MemDb(); IDb blockInfoDb = new MemDb(); IBlockTree blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockDb), specProvider, txPool, NullBloomStorage.Instance, LimboLogs.Instance); IReceiptStorage receiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new VirtualMachine(_stateProvider, storageProvider, new BlockhashProvider(blockTree, LimboLogs.Instance), specProvider, LimboLogs.Instance); TransactionProcessor txProcessor = new TransactionProcessor(specProvider, _stateProvider, storageProvider, virtualMachine, LimboLogs.Instance); IBlockProcessor blockProcessor = new BlockProcessor(specProvider, Always.Valid, new RewardCalculator(specProvider), txProcessor, _stateDb, codeDb, _stateProvider, storageProvider, txPool, receiptStorage, LimboLogs.Instance); IFilterStore filterStore = new FilterStore(); IFilterManager filterManager = new FilterManager(filterStore, blockProcessor, txPool, LimboLogs.Instance); _blockchainBridge = new BlockchainBridge(stateReader, _stateProvider, storageProvider, blockTree, txPool, receiptStorage, filterStore, filterManager, NullWallet.Instance, txProcessor, ethereumEcdsa, NullBloomStorage.Instance, LimboLogs.Instance, false); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ethereumEcdsa, txPool, LimboLogs.Instance), LimboLogs.Instance, true); blockchainProcessor.Start(); ManualResetEventSlim resetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (s, e) => { Console.WriteLine(e.Block.Header.Hash); if (e.Block.Number == 9) { resetEvent.Set(); } }; var genesisBlockBuilder = Build.A.Block.Genesis.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f")); if (auRa) { genesisBlockBuilder.WithAura(0, new byte[65]); } Block genesis = genesisBlockBuilder.TestObject; blockTree.SuggestBlock(genesis); Block previousBlock = genesis; for (int i = 1; i < 10; i++) { List <Transaction> transactions = new List <Transaction>(); for (int j = 0; j < i; j++) { transactions.Add(Build.A.Transaction.WithNonce((UInt256)j).SignedAndResolved().TestObject); } BlockBuilder builder = Build.A.Block.WithNumber(i).WithParent(previousBlock).WithTransactions(transactions.ToArray()).WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f")); if (auRa) { builder.WithAura(i, i.ToByteArray()); } Block block = builder.TestObject; blockTree.SuggestBlock(block); previousBlock = block; } IReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(); IReceiptFinder receiptFinder = new FullInfoReceiptFinder(receiptStorage, receiptsRecovery, blockTree); resetEvent.Wait(2000); _traceModule = new TraceModule(receiptFinder, new Tracer(_stateProvider, blockchainProcessor), _blockchainBridge); _blockTree = blockTree; }
private static async Task RunBenchmarkBlocks() { Rlp.RegisterDecoders(typeof(ParityTraceDecoder).Assembly); /* logging & instrumentation */ _logManager = new NLogManager("perfTest.logs.txt", null); _logger = _logManager.GetClassLogger(); if (_logger.IsInfo) { _logger.Info("Deleting state DBs"); } DeleteDb(FullStateDbPath); DeleteDb(FullCodeDbPath); DeleteDb(FullReceiptsDbPath); DeleteDb(FullPendingTxsDbPath); if (_logger.IsInfo) { _logger.Info("State DBs deleted"); } /* load spec */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"chainspec", "ropsten.json")); _logger.Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); _logger.Info($"ChainSpec loaded"); var specProvider = new ChainSpecBasedSpecProvider(chainSpec); IRewardCalculator rewardCalculator = new RewardCalculator(specProvider); var dbProvider = new RocksDbProvider(DbBasePath, DbConfig.Default, _logManager, true, true); var stateDb = dbProvider.StateDb; var codeDb = dbProvider.CodeDb; var traceDb = dbProvider.TraceDb; var blocksDb = dbProvider.BlocksDb; var headersDb = dbProvider.HeadersDb; var blockInfosDb = dbProvider.BlockInfosDb; var receiptsDb = dbProvider.ReceiptsDb; /* state & storage */ var stateProvider = new StateProvider(stateDb, codeDb, _logManager); var storageProvider = new StorageProvider(stateDb, stateProvider, _logManager); var ethereumSigner = new EthereumEcdsa(specProvider, _logManager); var transactionPool = new TxPool( NullTxStorage.Instance, Timestamper.Default, ethereumSigner, specProvider, new TxPoolConfig(), stateProvider, _logManager); var blockInfoRepository = new ChainLevelInfoRepository(blockInfosDb); var blockTree = new UnprocessedBlockTreeWrapper(new BlockTree(blocksDb, headersDb, blockInfosDb, blockInfoRepository, specProvider, transactionPool, _logManager)); var receiptStorage = new InMemoryReceiptStorage(); IBlockDataRecoveryStep recoveryStep = new TxSignaturesRecoveryStep(ethereumSigner, transactionPool, _logManager); /* blockchain processing */ IList <IAdditionalBlockProcessor> blockProcessors = new List <IAdditionalBlockProcessor>(); var blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, specProvider, _logManager); var processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, _logManager); ISealValidator sealValidator; if (specProvider.ChainId == RopstenSpecProvider.Instance.ChainId) { var difficultyCalculator = new DifficultyCalculator(specProvider); sealValidator = new EthashSealValidator(_logManager, difficultyCalculator, new Ethash(_logManager)); } else if (chainSpec.SealEngineType == SealEngineType.Clique) { var snapshotManager = new SnapshotManager(CliqueConfig.Default, blocksDb, blockTree, ethereumSigner, _logManager); sealValidator = new CliqueSealValidator(CliqueConfig.Default, snapshotManager, _logManager); rewardCalculator = NoBlockRewards.Instance; recoveryStep = new CompositeDataRecoveryStep(recoveryStep, new AuthorRecoveryStep(snapshotManager)); } else if (chainSpec.SealEngineType == SealEngineType.AuRa) { var abiEncoder = new AbiEncoder(); var validatorProcessor = new AuRaAdditionalBlockProcessorFactory(dbProvider.StateDb, stateProvider, abiEncoder, processor, blockTree, receiptStorage, _logManager) .CreateValidatorProcessor(chainSpec.AuRa.Validators); sealValidator = new AuRaSealValidator(chainSpec.AuRa, new AuRaStepCalculator(chainSpec.AuRa.StepDuration, new Timestamper()), validatorProcessor, ethereumSigner, _logManager); rewardCalculator = new AuRaRewardCalculator(chainSpec.AuRa, abiEncoder, processor); blockProcessors.Add(validatorProcessor); } else { throw new NotSupportedException(); } /* store & validation */ var headerValidator = new HeaderValidator(blockTree, sealValidator, specProvider, _logManager); var ommersValidator = new OmmersValidator(blockTree, headerValidator, _logManager); var transactionValidator = new TxValidator(chainSpec.ChainId); var blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, _logManager); /* blockchain processing */ var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, traceDb, stateProvider, storageProvider, transactionPool, receiptStorage, _logManager, blockProcessors); var blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, recoveryStep, _logManager, true, false); if (chainSpec.SealEngineType == SealEngineType.AuRa) { stateProvider.CreateAccount(Address.Zero, UInt256.Zero); storageProvider.Commit(); stateProvider.Commit(Homestead.Instance); var finalizationManager = new AuRaBlockFinalizationManager(blockTree, blockInfoRepository, blockProcessor, blockProcessors.OfType <IAuRaValidator>().First(), _logManager); } foreach ((Address address, ChainSpecAllocation allocation) in chainSpec.Allocations) { stateProvider.CreateAccount(address, allocation.Balance); if (allocation.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Code); stateProvider.UpdateCodeHash(address, codeHash, specProvider.GenesisSpec); } if (allocation.Constructor != null) { Transaction constructorTransaction = new Transaction(true) { SenderAddress = address, Init = allocation.Constructor, GasLimit = chainSpec.Genesis.GasLimit }; processor.Execute(constructorTransaction, chainSpec.Genesis.Header, NullTxTracer.Instance); } } _logger.Info($"Allocations configured, committing..."); stateProvider.Commit(specProvider.GenesisSpec); _logger.Info($"Finalizing genesis..."); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; chainSpec.Genesis.Header.Hash = BlockHeader.CalculateHash(chainSpec.Genesis.Header); if (chainSpec.Genesis.Hash != blockTree.Genesis.Hash) { throw new Exception("Unexpected genesis hash"); } _logger.Info($"Starting benchmark processor..."); /* start processing */ BigInteger totalGas = BigInteger.Zero; Stopwatch stopwatch = new Stopwatch(); Block currentHead; long maxMemory = 0; blockTree.NewHeadBlock += (sender, args) => { currentHead = args.Block; if (currentHead.Number == 0) { return; } maxMemory = Math.Max(maxMemory, GC.GetTotalMemory(false)); totalGas += currentHead.GasUsed; if ((BigInteger)args.Block.Number % 10000 == 9999) { stopwatch.Stop(); long ms = 1_000L * stopwatch.ElapsedTicks / Stopwatch.Frequency; BigInteger number = args.Block.Number + 1; _logger.Warn($"TOTAL after {number} (ms) : " + ms); _logger.Warn($"TOTAL after {number} blocks/s : {(decimal) currentHead.Number / (ms / 1000m),5}"); _logger.Warn($"TOTAL after {number} Mgas/s : {((decimal) totalGas / 1000000) / (ms / 1000m),5}"); _logger.Warn($"TOTAL after {number} max mem : {maxMemory}"); _logger.Warn($"TOTAL after {number} GC (0/1/2) : {GC.CollectionCount(0)}/{GC.CollectionCount(1)}/{GC.CollectionCount(2)}"); _logger.Warn($"Is server GC {number} : {System.Runtime.GCSettings.IsServerGC}"); _logger.Warn($"GC latency mode {number} : {System.Runtime.GCSettings.LatencyMode}"); _logger.Warn($"TOTAL after {number} blocks DB reads : {Store.Metrics.BlocksDbReads}"); _logger.Warn($"TOTAL after {number} blocks DB writes : {Store.Metrics.BlocksDbWrites}"); _logger.Warn($"TOTAL after {number} infos DB reads : {Store.Metrics.BlockInfosDbReads}"); _logger.Warn($"TOTAL after {number} infos DB writes : {Store.Metrics.BlockInfosDbWrites}"); _logger.Warn($"TOTAL after {number} state tree reads : {Store.Metrics.StateTreeReads}"); _logger.Warn($"TOTAL after {number} state tree writes : {Store.Metrics.StateTreeWrites}"); _logger.Warn($"TOTAL after {number} state DB reads : {Store.Metrics.StateDbReads}"); _logger.Warn($"TOTAL after {number} state DB writes : {Store.Metrics.StateDbWrites}"); _logger.Warn($"TOTAL after {number} storage tree reads : {Store.Metrics.StorageTreeReads}"); _logger.Warn($"TOTAL after {number} storage tree writes : {Store.Metrics.StorageTreeWrites}"); _logger.Warn($"TOTAL after {number} tree node hash : {Store.Metrics.TreeNodeHashCalculations}"); _logger.Warn($"TOTAL after {number} tree node RLP decode : {Store.Metrics.TreeNodeRlpDecodings}"); _logger.Warn($"TOTAL after {number} tree node RLP encode : {Store.Metrics.TreeNodeRlpEncodings}"); _logger.Warn($"TOTAL after {number} code DB reads : {Store.Metrics.CodeDbReads}"); _logger.Warn($"TOTAL after {number} code DB writes : {Store.Metrics.CodeDbWrites}"); _logger.Warn($"TOTAL after {number} receipts DB reads : {Store.Metrics.ReceiptsDbReads}"); _logger.Warn($"TOTAL after {number} receipts DB writes : {Store.Metrics.ReceiptsDbWrites}"); _logger.Warn($"TOTAL after {number} other DB reads : {Store.Metrics.OtherDbReads}"); _logger.Warn($"TOTAL after {number} other DB writes : {Store.Metrics.OtherDbWrites}"); _logger.Warn($"TOTAL after {number} EVM exceptions : {Evm.Metrics.EvmExceptions}"); _logger.Warn($"TOTAL after {number} SLOAD opcodes : {Evm.Metrics.SloadOpcode}"); _logger.Warn($"TOTAL after {number} SSTORE opcodes : {Evm.Metrics.SstoreOpcode}"); _logger.Warn($"TOTAL after {number} EXP opcodes : {Evm.Metrics.ModExpOpcode}"); _logger.Warn($"TOTAL after {number} BLOCKHASH opcodes : {Evm.Metrics.BlockhashOpcode}"); _logger.Warn($"TOTAL after {number} EVM calls : {Evm.Metrics.Calls}"); _logger.Warn($"TOTAL after {number} RIPEMD Precompiles : {Evm.Metrics.Ripemd160Precompile}"); _logger.Warn($"TOTAL after {number} SHA256 Precompiles : {Evm.Metrics.Sha256Precompile}"); // disk space stopwatch.Start(); } }; bool isStarted = false; TaskCompletionSource <object> completionSource = new TaskCompletionSource <object>(); blockTree.NewBestSuggestedBlock += (sender, args) => { if (!isStarted) { blockchainProcessor.Process(blockTree.FindBlock(blockTree.Genesis.Hash, BlockTreeLookupOptions.RequireCanonical), ProcessingOptions.None, NullBlockTracer.Instance); stopwatch.Start(); blockchainProcessor.Start(); isStarted = true; } if (args.Block.Number == BlocksToLoad) { completionSource.SetResult(null); } }; await Task.WhenAny(completionSource.Task, blockTree.LoadBlocksFromDb(CancellationToken.None, 0, 10000, BlocksToLoad)); await blockchainProcessor.StopAsync(true).ContinueWith( t => { if (t.IsFaulted) { _logger.Error("processing failed", t.Exception); _logger.Error("inner", t.Exception.InnerException); Console.ReadLine(); } _logger.Info("Block processing completed."); }); stopwatch.Stop(); Console.ReadLine(); }
public void Initialize() { Rlp.RegisterDecoders(typeof(ParityTraceDecoder).Assembly); _ethSerializer = new EthereumJsonSerializer(); ISpecProvider specProvider = MainNetSpecProvider.Instance; IEthereumEcdsa ethereumEcdsa = new EthereumEcdsa(specProvider, LimboLogs.Instance); ITxStorage txStorage = new InMemoryTxStorage(); ISnapshotableDb stateDb = new StateDb(); ISnapshotableDb codeDb = new StateDb(); IStateReader stateReader = new StateReader(stateDb, codeDb, LimboLogs.Instance); IStateProvider stateProvider = new StateProvider(stateDb, codeDb, LimboLogs.Instance); stateProvider.CreateAccount(TestItem.AddressA, 1000.Ether()); stateProvider.CreateAccount(TestItem.AddressB, 1000.Ether()); stateProvider.CreateAccount(TestItem.AddressC, 1000.Ether()); byte[] code = Bytes.FromHexString("0xabcd"); Keccak codeHash = Keccak.Compute(code); stateProvider.UpdateCode(code); stateProvider.UpdateCodeHash(TestItem.AddressA, codeHash, specProvider.GenesisSpec); IStorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, LimboLogs.Instance); storageProvider.Set(new StorageAddress(TestItem.AddressA, UInt256.One), Bytes.FromHexString("0xabcdef")); storageProvider.Commit(); stateProvider.Commit(specProvider.GenesisSpec); ITxPool txPool = new TxPool(txStorage, Timestamper.Default, ethereumEcdsa, specProvider, new TxPoolConfig(), stateProvider, LimboLogs.Instance); IDb blockDb = new MemDb(); IDb headerDb = new MemDb(); IDb blockInfoDb = new MemDb(); IDb traceDb = new MemDb(); IBlockTree blockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockDb), specProvider, txPool, LimboLogs.Instance); IReceiptStorage receiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new VirtualMachine(stateProvider, storageProvider, new BlockhashProvider(blockTree, LimboLogs.Instance), specProvider, LimboLogs.Instance); TransactionProcessor txProcessor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, LimboLogs.Instance); IBlockProcessor blockProcessor = new BlockProcessor(specProvider, AlwaysValidBlockValidator.Instance, new RewardCalculator(specProvider), txProcessor, stateDb, codeDb, traceDb, stateProvider, storageProvider, txPool, receiptStorage, LimboLogs.Instance); IFilterStore filterStore = new FilterStore(); IFilterManager filterManager = new FilterManager(filterStore, blockProcessor, txPool, LimboLogs.Instance); _blockchainBridge = new BlockchainBridge(stateReader, stateProvider, storageProvider, blockTree, txPool, receiptStorage, filterStore, filterManager, NullWallet.Instance, txProcessor, ethereumEcdsa); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ethereumEcdsa, txPool, LimboLogs.Instance), LimboLogs.Instance, true, true); blockchainProcessor.Start(); ManualResetEventSlim resetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (s, e) => { if (e.Block.Number == 9) { resetEvent.Set(); } }; Block genesis = Build.A.Block.Genesis.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f")).TestObject; blockTree.SuggestBlock(genesis); Block previousBlock = genesis; for (int i = 1; i < 10; i++) { Block block = Build.A.Block.WithNumber(i).WithParent(previousBlock).WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f")).TestObject; blockTree.SuggestBlock(block); previousBlock = block; } resetEvent.Wait(); _ethModule = new EthModule(LimboLogs.Instance, _blockchainBridge); _blockTree = blockTree; }
protected virtual async Task <TestBlockchain> Build(ISpecProvider specProvider = null) { Timestamper = new ManualTimestamper(new DateTime(2020, 2, 15, 12, 50, 30, DateTimeKind.Utc)); JsonSerializer = new EthereumJsonSerializer(); SpecProvider = specProvider ?? MainnetSpecProvider.Instance; EthereumEcdsa = new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance); ITxStorage txStorage = new InMemoryTxStorage(); DbProvider = new MemDbProvider(); State = new StateProvider(StateDb, CodeDb, LimboLogs.Instance); State.CreateAccount(TestItem.AddressA, 1000.Ether()); State.CreateAccount(TestItem.AddressB, 1000.Ether()); State.CreateAccount(TestItem.AddressC, 1000.Ether()); byte[] code = Bytes.FromHexString("0xabcd"); Keccak codeHash = Keccak.Compute(code); State.UpdateCode(code); State.UpdateCodeHash(TestItem.AddressA, codeHash, SpecProvider.GenesisSpec); Storage = new StorageProvider(StateDb, State, LimboLogs.Instance); Storage.Set(new StorageCell(TestItem.AddressA, UInt256.One), Bytes.FromHexString("0xabcdef")); Storage.Commit(); State.Commit(SpecProvider.GenesisSpec); State.CommitTree(); TxPool = new TxPool.TxPool(txStorage, Timestamper, EthereumEcdsa, SpecProvider, new TxPoolConfig(), State, LimboLogs.Instance); IDb blockDb = new MemDb(); IDb headerDb = new MemDb(); IDb blockInfoDb = new MemDb(); BlockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockDb), SpecProvider, TxPool, NullBloomStorage.Instance, LimboLogs.Instance); ReceiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new VirtualMachine(State, Storage, new BlockhashProvider(BlockTree, LimboLogs.Instance), SpecProvider, LimboLogs.Instance); TxProcessor = new TransactionProcessor(SpecProvider, State, Storage, virtualMachine, LimboLogs.Instance); BlockProcessor = CreateBlockProcessor(); BlockchainProcessor chainProcessor = new BlockchainProcessor(BlockTree, BlockProcessor, new TxSignaturesRecoveryStep(EthereumEcdsa, TxPool, LimboLogs.Instance), LimboLogs.Instance, BlockchainProcessor.Options.Default); chainProcessor.Start(); StateReader = new StateReader(StateDb, CodeDb, LimboLogs.Instance); TxPoolTxSource txPoolTxSource = new TxPoolTxSource(TxPool, StateReader, LimboLogs.Instance); ISealer sealer = new FakeSealer(TimeSpan.Zero); BlockProducer = new TestBlockProducer(txPoolTxSource, chainProcessor, State, sealer, BlockTree, chainProcessor, Timestamper, LimboLogs.Instance); BlockProducer.Start(); _resetEvent = new AutoResetEvent(false); BlockTree.NewHeadBlock += (s, e) => { Console.WriteLine(e.Block.Header.Hash); _resetEvent.Set(); }; var genesis = GetGenesisBlock(); BlockTree.SuggestBlock(genesis); await _resetEvent.WaitOneAsync(CancellationToken.None); await AddBlocksOnStart(); return(this); }