public void Rinkeby_loads_properly() { ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/rinkeby.json"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); ChainSpecBasedSpecProvider provider = new ChainSpecBasedSpecProvider(chainSpec); RinkebySpecProvider rinkeby = RinkebySpecProvider.Instance; IReleaseSpec oldRinkebySpec = rinkeby.GetSpec(3660663); IReleaseSpec newRinkebySpec = provider.GetSpec(3660663); PropertyInfo[] propertyInfos = typeof(IReleaseSpec).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo propertyInfo in propertyInfos.Where(pi => pi.Name != "MaximumExtraDataSize" && pi.Name != "Registrar" && pi.Name != "BlockReward" && pi.Name != "DifficultyBombDelay" && pi.Name != "DifficultyBoundDivisor")) { object a = propertyInfo.GetValue(oldRinkebySpec); object b = propertyInfo.GetValue(newRinkebySpec); Assert.AreEqual(a, b, propertyInfo.Name); } }
private static ChainSpec LoadChainSpec(string path) { var data = File.ReadAllText(path); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); return(chainSpec); }
private static void Test(long head, Keccak genesisHash, string forkHashHex, long next, string description, ISpecProvider specProvider, string chainSpec) { Test(head, genesisHash, forkHashHex, next, description, specProvider); ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec spec = loader.Load(File.ReadAllText("../../../../Chains/" + chainSpec)); ChainSpecBasedSpecProvider provider = new ChainSpecBasedSpecProvider(spec); Test(head, genesisHash, forkHashHex, next, description, provider); }
public void Can_load_rinkeby() { byte[] data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/rinkeby.json")); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); Assert.AreEqual(4, chainSpec.ChainId, $"{nameof(chainSpec.ChainId)}"); Assert.AreEqual("Rinkeby", chainSpec.Name, $"{nameof(chainSpec.Name)}"); Assert.AreEqual(SealEngineType.Clique, chainSpec.SealEngineType, "engine"); }
public void Can_load_spaceneth() { byte[] data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/spaceneth.json")); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); Assert.AreEqual(99, chainSpec.ChainId, $"{nameof(chainSpec.ChainId)}"); Assert.AreEqual("Spaceneth", chainSpec.Name, $"{nameof(chainSpec.Name)}"); Assert.AreEqual("spaceneth", chainSpec.DataDir, $"{nameof(chainSpec.Name)}"); Assert.AreEqual(SealEngineType.NethDev, chainSpec.SealEngineType, "engine"); }
public void Fork_id_and_hash_as_expected_with_merge_fork_id(long head, string forkHashHex, long next, string description) { ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec spec = loader.Load(File.ReadAllText(Path.Combine("../../../../Chains", "foundation.json"))); spec.Parameters.MergeForkIdTransition = 21_000_000L; spec.MergeForkIdBlockNumber = 21_000_000L; ChainSpecBasedSpecProvider provider = new ChainSpecBasedSpecProvider(spec); Test(head, KnownHashes.MainnetGenesis, forkHashHex, next, description, provider); }
private ChainSpec LoadChainSpec(string chainSpecFile) { _logger.Info($"Loading ChainSpec from {chainSpecFile}"); ChainSpecLoader loader = new ChainSpecLoader(new UnforgivingJsonSerializer()); if (!Path.IsPathRooted(chainSpecFile)) { chainSpecFile = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, chainSpecFile)); } ChainSpec chainSpec = loader.Load(File.ReadAllBytes(chainSpecFile)); return(chainSpec); }
public void Can_load_ropsten() { byte[] data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/ropsten.json")); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); Assert.AreEqual(3, chainSpec.ChainId, $"{nameof(chainSpec.ChainId)}"); Assert.AreEqual("Ropsten", chainSpec.Name, $"{nameof(chainSpec.Name)}"); Assert.NotNull(chainSpec.Genesis, $"{nameof(ChainSpec.Genesis)}"); Assert.AreEqual(0x0000000000000042UL, chainSpec.Genesis.Header.Nonce, $"genesis {nameof(BlockHeader.Nonce)}"); Assert.AreEqual(Keccak.Zero, chainSpec.Genesis.Header.MixHash, $"genesis {nameof(BlockHeader.MixHash)}"); Assert.AreEqual(0x100000L, (long)chainSpec.Genesis.Header.Difficulty, $"genesis {nameof(BlockHeader.Difficulty)}"); Assert.AreEqual(Address.Zero, chainSpec.Genesis.Header.Beneficiary, $"genesis {nameof(BlockHeader.Beneficiary)}"); Assert.AreEqual(0x00L, (long)chainSpec.Genesis.Header.Timestamp, $"genesis {nameof(BlockHeader.Timestamp)}"); Assert.AreEqual(Keccak.Zero, chainSpec.Genesis.Header.ParentHash, $"genesis {nameof(BlockHeader.ParentHash)}"); Assert.AreEqual( Bytes.FromHexString("0x3535353535353535353535353535353535353535353535353535353535353535"), chainSpec.Genesis.Header.ExtraData, $"genesis {nameof(BlockHeader.ExtraData)}"); Assert.AreEqual(0x1000000L, chainSpec.Genesis.Header.GasLimit, $"genesis {nameof(BlockHeader.GasLimit)}"); Assert.NotNull(chainSpec.Allocations, $"{nameof(ChainSpec.Allocations)}"); Assert.AreEqual(257, chainSpec.Allocations.Count, $"allocations count"); Assert.AreEqual( UInt256.Zero, chainSpec.Allocations[new Address("0000000000000000000000000000000000000018")], "account 0000000000000000000000000000000000000018"); Assert.AreEqual( UInt256.One, chainSpec.Allocations[new Address("0000000000000000000000000000000000000001")], "account 0000000000000000000000000000000000000001"); Assert.AreEqual( UInt256.Parse("1000000000000000000000000000000"), chainSpec.Allocations[new Address("874b54a8bd152966d63f706bae1ffeb0411921e5")], "account 874b54a8bd152966d63f706bae1ffeb0411921e5"); Assert.AreEqual(SealEngineType.Ethash, chainSpec.SealEngineType, "engine"); Assert.AreEqual((UInt256?)0, chainSpec.HomesteadBlockNumber, "homestead no"); Assert.AreEqual(null, chainSpec.DaoForkBlockNumber, "dao no"); Assert.AreEqual((UInt256?)0, chainSpec.TangerineWhistleBlockNumber, "tw no"); Assert.AreEqual((UInt256?)10, chainSpec.SpuriousDragonBlockNumber, "sd no"); Assert.AreEqual((UInt256?)1700000, chainSpec.ByzantiumBlockNumber, "byzantium no"); Assert.AreEqual((UInt256?)4230000, chainSpec.ConstantinopleBlockNumber, "constantinople no"); }
public void Can_load_mainnet() { byte[] data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/foundation.json")); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); Assert.AreEqual(1, chainSpec.ChainId, $"{nameof(chainSpec.ChainId)}"); Assert.AreEqual("Foundation", chainSpec.Name, $"{nameof(chainSpec.Name)}"); Assert.AreEqual("ethereum", chainSpec.DataDir, $"{nameof(chainSpec.Name)}"); Assert.AreEqual(SealEngineType.Ethash, chainSpec.SealEngineType, "engine"); Assert.AreEqual((UInt256?)1150000, chainSpec.HomesteadBlockNumber, "homestead no"); Assert.AreEqual((UInt256?)1920000, chainSpec.DaoForkBlockNumber, "dao no"); Assert.AreEqual((UInt256?)2463000, chainSpec.TangerineWhistleBlockNumber, "tw no"); Assert.AreEqual((UInt256?)2675000, chainSpec.SpuriousDragonBlockNumber, "sd no"); Assert.AreEqual((UInt256?)4370000, chainSpec.ByzantiumBlockNumber, "byzantium no"); Assert.AreEqual((UInt256?)7080000, chainSpec.ConstantinopleBlockNumber, "constantinople no"); }
public void Mainnet_loads_properly() { ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../Chains/foundation.json"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); ChainSpecBasedSpecProvider provider = new ChainSpecBasedSpecProvider(chainSpec); MainNetSpecProvider mainnet = MainNetSpecProvider.Instance; IReleaseSpec oldSpec = mainnet.GetSpec(7280000); IReleaseSpec newSpec = provider.GetSpec(7280000); PropertyInfo[] propertyInfos = typeof(IReleaseSpec).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo propertyInfo in propertyInfos) { object a = propertyInfo.GetValue(oldSpec); object b = propertyInfo.GetValue(newSpec); Assert.AreEqual(a, b, propertyInfo.Name); } }
public void Can_load_ropsten() { byte[] data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/ropsten.json")); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new UnforgivingJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); Assert.AreEqual(3, chainSpec.ChainId, $"{nameof(chainSpec.ChainId)}"); Assert.AreEqual("Ropsten", chainSpec.Name, $"{nameof(chainSpec.Name)}"); Assert.NotNull(chainSpec.Genesis, $"{nameof(ChainSpec.Genesis)}"); Assert.AreEqual(0x0000000000000042UL, chainSpec.Genesis.Header.Nonce, $"genesis {nameof(BlockHeader.Nonce)}"); Assert.AreEqual(Keccak.Zero, chainSpec.Genesis.Header.MixHash, $"genesis {nameof(BlockHeader.MixHash)}"); Assert.AreEqual(0x100000L, (long)chainSpec.Genesis.Header.Difficulty, $"genesis {nameof(BlockHeader.Difficulty)}"); Assert.AreEqual(0x100000L, (long)chainSpec.Genesis.Header.Difficulty, $"genesis {nameof(BlockHeader.Difficulty)}"); Assert.AreEqual(Address.Zero, chainSpec.Genesis.Header.Beneficiary, $"genesis {nameof(BlockHeader.Beneficiary)}"); Assert.AreEqual(0x00L, (long)chainSpec.Genesis.Header.Timestamp, $"genesis {nameof(BlockHeader.Timestamp)}"); Assert.AreEqual(Keccak.Zero, chainSpec.Genesis.Header.ParentHash, $"genesis {nameof(BlockHeader.ParentHash)}"); Assert.AreEqual( (byte[])new Hex("0x3535353535353535353535353535353535353535353535353535353535353535"), chainSpec.Genesis.Header.ExtraData, $"genesis {nameof(BlockHeader.ExtraData)}"); Assert.AreEqual(0x1000000L, chainSpec.Genesis.Header.GasLimit, $"genesis {nameof(BlockHeader.GasLimit)}"); Assert.NotNull(chainSpec.Allocations, $"{nameof(ChainSpec.Allocations)}"); Assert.AreEqual(257, chainSpec.Allocations.Count, $"allocations count"); Assert.AreEqual( BigInteger.Zero, chainSpec.Allocations[new Address("0000000000000000000000000000000000000018")], "account 0000000000000000000000000000000000000018"); Assert.AreEqual( BigInteger.One, chainSpec.Allocations[new Address("0000000000000000000000000000000000000001")], "account 0000000000000000000000000000000000000001"); Assert.AreEqual( BigInteger.Parse("1000000000000000000000000000000"), chainSpec.Allocations[new Address("874b54a8bd152966d63f706bae1ffeb0411921e5")], "account 874b54a8bd152966d63f706bae1ffeb0411921e5"); }
public void Can_load_goerli() { byte[] data = File.ReadAllBytes(Path.Combine(TestContext.CurrentContext.WorkDirectory, "../../../../", "Chains/goerli.json")); ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new EthereumJsonSerializer()); ChainSpec chainSpec = chainSpecLoader.Load(data); Assert.AreEqual(5, chainSpec.ChainId, $"{nameof(chainSpec.ChainId)}"); Assert.AreEqual("Görli Testnet", chainSpec.Name, $"{nameof(chainSpec.Name)}"); Assert.AreEqual("goerli", chainSpec.DataDir, $"{nameof(chainSpec.DataDir)}"); Assert.AreEqual(SealEngineType.Clique, chainSpec.SealEngineType, "engine"); Assert.AreEqual(15UL, chainSpec.CliquePeriod); Assert.AreEqual(30000UL, chainSpec.CliqueEpoch); Assert.AreEqual(UInt256.Zero, chainSpec.CliqueReward); Assert.AreEqual(null, chainSpec.HomesteadBlockNumber, "homestead no"); Assert.AreEqual(null, chainSpec.DaoForkBlockNumber, "dao no"); Assert.AreEqual((UInt256?)0, chainSpec.TangerineWhistleBlockNumber, "tw no"); Assert.AreEqual((UInt256?)0, chainSpec.SpuriousDragonBlockNumber, "sd no"); Assert.AreEqual((UInt256?)0, chainSpec.ByzantiumBlockNumber, "byzantium no"); Assert.AreEqual((UInt256?)0, chainSpec.ConstantinopleBlockNumber, "constantinople no"); }
public static async Task <TTest> ForTest <TTest, TTestClass>(string testSuffix = null) where TTest : TestContractBlockchain, new() { (ChainSpec ChainSpec, ISpecProvider SpecProvider) GetSpecProvider() { ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); var name = string.IsNullOrEmpty(testSuffix) ? $"{typeof(TTestClass).FullName}.json" : $"{typeof(TTestClass).FullName}.{testSuffix}.json"; using var stream = typeof(TTestClass).Assembly.GetManifestResourceStream(name); using var reader = new StreamReader(stream ?? new MemoryStream()); var chainSpec = loader.Load(reader.ReadToEnd()); ChainSpecBasedSpecProvider chainSpecBasedSpecProvider = new ChainSpecBasedSpecProvider(chainSpec); return(chainSpec, chainSpecBasedSpecProvider); } var provider = GetSpecProvider(); var test = new TTest() { ChainSpec = provider.ChainSpec }; return((TTest)await test.Build(provider.SpecProvider));; }
// 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 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 async Task Build_some_chain() { /* logging & instrumentation */ var logger = new OneLoggerLogManager(new SimpleConsoleLogger()); /* spec */ var blockMiningTime = TimeSpan.FromMilliseconds(500); var sealEngine = new FakeSealEngine(blockMiningTime); var specProvider = RopstenSpecProvider.Instance; /* store & validation */ var blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), specProvider, logger); var difficultyCalculator = new DifficultyCalculator(specProvider); var headerValidator = new HeaderValidator(difficultyCalculator, blockTree, sealEngine, specProvider, logger); var ommersValidator = new OmmersValidator(blockTree, headerValidator, logger); var transactionValidator = new TransactionValidator(new SignatureValidator(ChainId.Ropsten)); var blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, logger); /* state & storage */ var dbProvider = new MemDbProvider(logger); var stateTree = new StateTree(dbProvider.GetOrCreateStateDb()); var stateProvider = new StateProvider(stateTree, dbProvider.GetOrCreateCodeDb(), logger); var storageProvider = new StorageProvider(dbProvider, stateProvider, logger); /* blockchain processing */ var ethereumSigner = new EthereumSigner(specProvider, logger); var transactionStore = new TransactionStore(); var blockhashProvider = new BlockhashProvider(blockTree); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, logger); var processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, NullTracer.Instance, logger); var rewardCalculator = new RewardCalculator(specProvider); var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, dbProvider, stateProvider, storageProvider, transactionStore, logger); var blockchainProcessor = new BlockchainProcessor(blockTree, sealEngine, transactionStore, difficultyCalculator, blockProcessor, ethereumSigner, logger); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new UnforgivingJsonSerializer()); string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\..\Chains", "ropsten.json")); logger.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); foreach (KeyValuePair <Address, BigInteger> allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value); } 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 */ sealEngine.IsMining = true; var testTransactionsGenerator = new TestTransactionsGenerator(transactionStore, ethereumSigner, blockMiningTime, logger); testTransactionsGenerator.Start(); blockchainProcessor.Start(); blockTree.SuggestBlock(chainSpec.Genesis); BigInteger roughlyNumberOfBlocks = 6; Thread.Sleep(blockMiningTime * (int)roughlyNumberOfBlocks); await blockchainProcessor.StopAsync(false); Assert.GreaterOrEqual(blockTree.Head.Number, roughlyNumberOfBlocks - 2, "number of blocks"); Assert.GreaterOrEqual(blockTree.Head.TotalTransactions, roughlyNumberOfBlocks - 2, "number of transactions"); }
protected async Task StartRunners(IConfigProvider configProvider) { try { var initParams = configProvider.GetConfig <IInitConfig>(); var logManager = new NLogManager(initParams.LogFileName, initParams.LogDirectory); //discovering and setting local, remote ips for client machine var networkHelper = new NetworkHelper(Logger); var localHost = networkHelper.GetLocalIp()?.ToString() ?? "127.0.0.1"; var networkConfig = configProvider.GetConfig <INetworkConfig>(); networkConfig.MasterExternalIp = localHost; networkConfig.MasterHost = localHost; ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new UnforgivingJsonSerializer()); string path = initParams.ChainSpecPath; if (!Path.IsPathRooted(path)) { path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path)); } byte[] chainSpecData = File.ReadAllBytes(path); ChainSpec chainSpec = chainSpecLoader.Load(chainSpecData); var nodes = chainSpec.NetworkNodes.Select(nn => GetNode(nn, localHost)).ToArray(); networkConfig.BootNodes = nodes; networkConfig.DbBasePath = initParams.BaseDbPath; _ethereumRunner = new EthereumRunner(configProvider, networkHelper, logManager); await _ethereumRunner.Start().ContinueWith(x => { if (x.IsFaulted && Logger.IsError) { Logger.Error("Error during ethereum runner start", x.Exception); } }); if (initParams.JsonRpcEnabled) { Bootstrap.Instance.ConfigProvider = configProvider; Bootstrap.Instance.LogManager = logManager; Bootstrap.Instance.BlockchainBridge = _ethereumRunner.BlockchainBridge; Bootstrap.Instance.EthereumSigner = _ethereumRunner.EthereumSigner; _jsonRpcRunner = new JsonRpcRunner(configProvider, logManager); await _jsonRpcRunner.Start().ContinueWith(x => { if (x.IsFaulted && Logger.IsError) { Logger.Error("Error during jsonRpc runner start", x.Exception); } }); } else { if (Logger.IsInfo) { Logger.Info("Json RPC is disabled"); } } } catch (Exception e) { Logger.Error("Error while starting Nethermind.Runner", e); throw; } }
protected async Task StartRunners(InitParams initParams) { try { //TODO find better way to enforce assemblies with config impl are loaded IKeystoreConfig kConfig; INetworkConfig nConfig; IJsonRpcConfig jConfig; var configProvider = new JsonConfigProvider(); var logManager = new NLogManager(initParams.LogFileName); //configProvider.LoadJsonConfig(""); //discovering and setting local, remote ips for client machine var networkHelper = new NetworkHelper(Logger); var localHost = networkHelper.GetLocalIp()?.ToString() ?? "127.0.0.1"; var networkConfig = configProvider.GetConfig <NetworkConfig>(); networkConfig.MasterExternalIp = localHost; networkConfig.MasterHost = localHost; ChainSpecLoader chainSpecLoader = new ChainSpecLoader(new UnforgivingJsonSerializer()); string path = initParams.ChainSpecPath; if (!Path.IsPathRooted(path)) { path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path)); } byte[] chainSpecData = File.ReadAllBytes(path); ChainSpec chainSpec = chainSpecLoader.Load(chainSpecData); //Setting trusted nodes var nodes = chainSpec.NetworkNodes.Select(GetNode).ToArray(); networkConfig.TrustedPeers = nodes; networkConfig.BootNodes = nodes; networkConfig.DbBasePath = initParams.BaseDbPath; _ethereumRunner = new EthereumRunner(configProvider, networkHelper, logManager); await _ethereumRunner.Start(initParams); if (initParams.JsonRpcEnabled) { Bootstrap.Instance.ConfigProvider = configProvider; Bootstrap.Instance.LogManager = logManager; Bootstrap.Instance.BlockchainBridge = _ethereumRunner.BlockchainBridge; Bootstrap.Instance.EthereumSigner = _ethereumRunner.EthereumSigner; _jsonRpcRunner = new JsonRpcRunner(configProvider, Logger); await _jsonRpcRunner.Start(initParams); } else { if (Logger.IsInfoEnabled) { Logger.Info("Json RPC is disabled"); } } } catch (Exception e) { Logger.Error("Error while starting Nethermind.Runner", e); throw; } }
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"); }
public async Task Test() { TimeSpan miningDelay = TimeSpan.FromMilliseconds(50); /* logging & instrumentation */ var logger = new OneLoggerLogManager(new SimpleConsoleLogger(true)); /* spec */ var sealEngine = new FakeSealEngine(miningDelay); sealEngine.IsMining = true; var specProvider = RopstenSpecProvider.Instance; /* store & validation */ var blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), specProvider, logger); var difficultyCalculator = new DifficultyCalculator(specProvider); var headerValidator = new HeaderValidator(difficultyCalculator, blockTree, sealEngine, specProvider, logger); var ommersValidator = new OmmersValidator(blockTree, headerValidator, logger); var transactionValidator = new TransactionValidator(new SignatureValidator(ChainId.Ropsten)); var blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, logger); /* state & storage */ var codeDb = new MemDb(); var stateDb = new MemDb(); var stateTree = new StateTree(stateDb); var stateProvider = new StateProvider(stateTree, codeDb, logger); var storageDbProvider = new MemDbProvider(logger); var storageProvider = new StorageProvider(storageDbProvider, stateProvider, logger); /* blockchain processing */ var ethereumSigner = new EthereumSigner(specProvider, logger); var transactionStore = new TransactionStore(); var blockhashProvider = new BlockhashProvider(blockTree); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, logger); var processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, NullTracer.Instance, logger); var rewardCalculator = new RewardCalculator(specProvider); var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, storageDbProvider, stateProvider, storageProvider, transactionStore, logger); var blockchainProcessor = new BlockchainProcessor(blockTree, sealEngine, transactionStore, difficultyCalculator, blockProcessor, ethereumSigner, logger, new PerfService(NullLogManager.Instance)); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new UnforgivingJsonSerializer()); string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\..\Chains", "ropsten.json")); logger.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); foreach (KeyValuePair <Address, UInt256> allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value); } 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(); ManualResetEvent manualResetEvent = new ManualResetEvent(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.WaitOne(miningDelay * 12); await blockchainProcessor.StopAsync(true).ContinueWith( t => { if (t.IsFaulted) { throw t.Exception; } Assert.GreaterOrEqual((int)blockTree.Head.Number, 6); }); }