public void Storage_proofs_have_values_set_complex_2_setup() { byte[] a = Bytes.FromHexString("0x000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaa"); byte[] b = Bytes.FromHexString("0x0000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); byte[] c = Bytes.FromHexString("0x0000000000cccccccccccccccccccccccccccccccccccccccccccccccccccccc"); byte[] d = Bytes.FromHexString("0x0000000000dddddddddddddddddddddddddddddddddddddddddddddddddddddd"); byte[] e = Bytes.FromHexString("0x0000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); IDb memDb = new MemDb(); StateTree tree = new StateTree(memDb); StorageTree storageTree = new StorageTree(memDb); storageTree.Set(Keccak.Compute(a).Bytes, Rlp.Encode(Bytes.FromHexString("0xab12000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(Keccak.Compute(b).Bytes, Rlp.Encode(Bytes.FromHexString("0xab34000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(Keccak.Compute(c).Bytes, Rlp.Encode(Bytes.FromHexString("0xab56000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(Keccak.Compute(d).Bytes, Rlp.Encode(Bytes.FromHexString("0xab78000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(Keccak.Compute(e).Bytes, Rlp.Encode(Bytes.FromHexString("0xab9a000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Commit(); byte[] code = new byte[] { 1, 2, 3 }; Account account1 = Build.An.Account.WithBalance(1).WithStorageRoot(storageTree.RootHash).TestObject; Account account2 = Build.An.Account.WithBalance(2).TestObject; tree.Set(TestItem.AddressA, account1); tree.Set(TestItem.AddressB, account2); tree.Commit(); TreeDumper dumper = new TreeDumper(); tree.Accept(dumper, tree.RootHash, true); Console.WriteLine(dumper.ToString()); AccountProofCollector accountProofCollector = new AccountProofCollector(TestItem.AddressA, new byte[][] { a, b, c, d, e }); tree.Accept(accountProofCollector, tree.RootHash, true); AccountProof proof = accountProofCollector.BuildResult(); Assert.AreEqual("0xab12000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[0].Value.ToHexString(true)); Assert.AreEqual("0xab34000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[1].Value.ToHexString(true)); Assert.AreEqual("0xab56000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[2].Value.ToHexString(true)); Assert.AreEqual("0xab78000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[3].Value.ToHexString(true)); Assert.AreEqual("0xab9a000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[4].Value.ToHexString(true)); }
public void Proof_path_is_filled() { StateTree tree = new StateTree(); byte[] code = new byte[] { 1, 2, 3 }; Account account1 = Build.An.Account.WithBalance(1).WithStorageRoot(TestItem.KeccakA).TestObject; Account account2 = Build.An.Account.WithBalance(2).TestObject; tree.Set(TestItem.AddressA, account1); tree.Set(TestItem.AddressB, account2); tree.Commit(); AccountProofCollector accountProofCollector = new AccountProofCollector(TestItem.AddressA); tree.Accept(accountProofCollector, tree.RootHash, true); AccountProof proof = accountProofCollector.BuildResult(); Assert.AreEqual(3, proof.Proof.Length); }
public void Storage_proofs_length_is_as_expected() { StateTree tree = new StateTree(); byte[] code = new byte[] { 1, 2, 3 }; Account account1 = Build.An.Account.WithBalance(1).WithStorageRoot(TestItem.KeccakA).TestObject; Account account2 = Build.An.Account.WithBalance(2).TestObject; tree.Set(TestItem.AddressA, account1); tree.Set(TestItem.AddressB, account2); tree.Commit(); AccountProofCollector accountProofCollector = new AccountProofCollector(TestItem.AddressA, new[] { Bytes.FromHexString("0x0000000000000000000000000000000000000000000000000000000000000000"), Bytes.FromHexString("0x0000000000000000000000000000000000000000000000000000000000000001") }); tree.Accept(accountProofCollector, tree.RootHash, true); AccountProof proof = accountProofCollector.BuildResult(); Assert.AreEqual(2, proof.StorageProofs.Length); }
public void Storage_proofs_have_values_set_selective_setup() { Keccak a = new Keccak("0x000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaa"); Keccak b = new Keccak("0x0000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); Keccak c = new Keccak("0x00000000001ccccccccccccccccccccccccccccccccccccccccccccccccccccc"); Keccak d = new Keccak("0x00000000001ddddddddddddddddddddddddddddddddddddddddddddddddddddd"); Keccak e = new Keccak("0x00000000001eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); IDb memDb = new MemDb(); StateTree tree = new StateTree(memDb); StorageTree storageTree = new StorageTree(memDb); storageTree.Set(a.Bytes, Rlp.Encode(Bytes.FromHexString("0xab12000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(b.Bytes, Rlp.Encode(Bytes.FromHexString("0xab34000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(c.Bytes, Rlp.Encode(Bytes.FromHexString("0xab56000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(d.Bytes, Rlp.Encode(Bytes.FromHexString("0xab78000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Set(e.Bytes, Rlp.Encode(Bytes.FromHexString("0xab9a000000000000000000000000000000000000000000000000000000000000000000000000000000"))); storageTree.Commit(); byte[] code = new byte[] { 1, 2, 3 }; Account account1 = Build.An.Account.WithBalance(1).WithStorageRoot(storageTree.RootHash).TestObject; Account account2 = Build.An.Account.WithBalance(2).TestObject; tree.Set(TestItem.AddressA, account1); tree.Set(TestItem.AddressB, account2); tree.Commit(); TreeDumper dumper = new TreeDumper(); tree.Accept(dumper, memDb, tree.RootHash); Console.WriteLine(dumper.ToString()); ProofCollector proofCollector = new ProofCollector(TestItem.AddressA, new Keccak[] { a, c, e }); tree.Accept(proofCollector, memDb, tree.RootHash); AccountProof proof = proofCollector.BuildResult(); Assert.AreEqual("0xab12000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[0].Value.ToHexString(true)); Assert.AreEqual("0xab56000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[1].Value.ToHexString(true)); Assert.AreEqual("0xab9a000000000000000000000000000000000000000000000000000000000000000000000000000000", proof.StorageProofs[2].Value.ToHexString(true)); }
public void Create_commit_reset_change_balance_get() { MemDb db = new MemDb(); Account account = new Account(1); StateTree stateTree = new StateTree(new TrieStore(db, LimboLogs.Instance), LimboLogs.Instance); stateTree.Set(TestItem.AddressA, account); stateTree.Commit(0); Keccak rootHash = stateTree.RootHash; stateTree.RootHash = null; stateTree.RootHash = rootHash; stateTree.Get(TestItem.AddressA); account = account.WithChangedBalance(2); stateTree.Set(TestItem.AddressA, account); stateTree.Commit(0); Assert.AreEqual(2, db.Keys.Count); }
public void Non_existing_account_is_valid_even_when_leaf_is_the_last_part_of_the_proof() { StateTree tree = new StateTree(); Account account1 = Build.An.Account.WithBalance(1).TestObject; tree.Set(TestItem.AddressA, account1); tree.Commit(0); AccountProofCollector accountProofCollector = new AccountProofCollector(TestItem.AddressC, new UInt256[] { 1, 2, 3 }); tree.Accept(accountProofCollector, tree.RootHash, true); AccountProof proof = accountProofCollector.BuildResult(); proof.Proof.Should().HaveCount(1); Assert.AreEqual(TestItem.AddressC, proof.Address); Assert.AreEqual(Keccak.OfAnEmptyString, proof.CodeHash); Assert.AreEqual(Keccak.EmptyTreeHash, proof.StorageRoot); Assert.AreEqual(UInt256.Zero, proof.Balance); Assert.AreEqual(new byte[] { 0 }, proof.StorageProofs[0].Value); Assert.AreEqual(new byte[] { 0 }, proof.StorageProofs[1].Value); Assert.AreEqual(new byte[] { 0 }, proof.StorageProofs[2].Value); }
public static (StateTree stateTree, StorageTree storageTree) GetTrees(ITrieStore?store) { store ??= new TrieStore(new MemDb(), LimboLogs.Instance); var storageTree = new StorageTree(store, LimboLogs.Instance); storageTree.Set(SlotsWithPaths[0].Path, SlotsWithPaths[0].SlotRlpValue, false); storageTree.Set(SlotsWithPaths[1].Path, SlotsWithPaths[1].SlotRlpValue, false); storageTree.Set(SlotsWithPaths[2].Path, SlotsWithPaths[2].SlotRlpValue, false); storageTree.Set(SlotsWithPaths[3].Path, SlotsWithPaths[3].SlotRlpValue, false); storageTree.Set(SlotsWithPaths[4].Path, SlotsWithPaths[4].SlotRlpValue, false); storageTree.Set(SlotsWithPaths[5].Path, SlotsWithPaths[5].SlotRlpValue, false); storageTree.Commit(0); var account = Build.An.Account.WithBalance(1).WithStorageRoot(storageTree.RootHash).TestObject; var stateTree = new StateTree(store, LimboLogs.Instance); stateTree.Set(AccountAddress0, account); stateTree.Commit(0); return(stateTree, storageTree); }
// [TestCase(4, 16, 4, 4)] public void Fuzz_accounts( int accountsCount, int blocksCount, int uniqueValuesCount, int lookupLimit) { string fileName = Path.GetTempFileName(); //string fileName = "C:\\Temp\\fuzz.txt"; _logger.Info( $"Fuzzing with accounts: {accountsCount}, " + $"blocks {blocksCount}, " + $"values: {uniqueValuesCount}, " + $"lookup: {lookupLimit} into file {fileName}"); using FileStream fileStream = new FileStream(fileName, FileMode.Create); using StreamWriter streamWriter = new StreamWriter(fileStream); Queue <Keccak> rootQueue = new Queue <Keccak>(); MemDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, Prune.WhenCacheReaches(1.MB()), Persist.IfBlockOlderThan(lookupLimit), _logManager); StateTree patriciaTree = new StateTree(trieStore, _logManager); byte[][] accounts = new byte[accountsCount][]; byte[][] randomValues = new byte[uniqueValuesCount][]; for (int i = 0; i < randomValues.Length; i++) { bool isEmptyValue = _random.Next(0, 2) == 0; if (isEmptyValue) { randomValues[i] = Array.Empty <byte>(); } else { randomValues[i] = GenerateRandomAccountRlp(); } } for (int accountIndex = 0; accountIndex < accounts.Length; accountIndex++) { byte[] key = new byte[32]; ((UInt256)accountIndex).ToBigEndian(key); accounts[accountIndex] = key; } for (int blockNumber = 0; blockNumber < blocksCount; blockNumber++) { bool isEmptyBlock = _random.Next(5) == 0; if (!isEmptyBlock) { for (int i = 0; i < Math.Max(1, accountsCount / 8); i++) { int randomAccountIndex = _random.Next(accounts.Length); int randomValueIndex = _random.Next(randomValues.Length); byte[] account = accounts[randomAccountIndex]; byte[] value = randomValues[randomValueIndex]; streamWriter.WriteLine( $"Block {blockNumber} - setting {account.ToHexString()} = {value.ToHexString()}"); patriciaTree.Set(account, value); } } streamWriter.WriteLine( $"Commit block {blockNumber} | empty: {isEmptyBlock}"); patriciaTree.UpdateRootHash(); patriciaTree.Commit(blockNumber); rootQueue.Enqueue(patriciaTree.RootHash); } streamWriter.Flush(); fileStream.Seek(0, SeekOrigin.Begin); streamWriter.WriteLine($"DB size: {memDb.Keys.Count}"); _logger.Info($"DB size: {memDb.Keys.Count}"); int verifiedBlocks = 0; while (rootQueue.TryDequeue(out Keccak currentRoot)) { try { patriciaTree.RootHash = currentRoot; for (int i = 0; i < accounts.Length; i++) { patriciaTree.Get(accounts[i]); } _logger.Info($"Verified positive {verifiedBlocks}"); } catch (Exception ex) { if (verifiedBlocks % lookupLimit == 0) { throw new InvalidDataException(ex.ToString()); } else { _logger.Info($"Verified negative {verifiedBlocks}"); } } verifiedBlocks++; } }
private async Task InitBlockchain(InitParams initParams) { ChainSpec chainSpec = LoadChainSpec(initParams.ChainSpecPath); /* spec */ // TODO: rebuild to use chainspec ISpecProvider specProvider; if (chainSpec.ChainId == RopstenSpecProvider.Instance.ChainId) { specProvider = RopstenSpecProvider.Instance; } else if (chainSpec.ChainId == MainNetSpecProvider.Instance.ChainId) { specProvider = MainNetSpecProvider.Instance; } else { throw new NotSupportedException($"Not yet tested, not yet supported ChainId {chainSpec.ChainId}"); } var ethereumSigner = new EthereumSigner(specProvider, _logManager); var transactionStore = new TransactionStore(); var sealEngine = ConfigureSealEngine(transactionStore, ethereumSigner, initParams); /* sync */ var blocksDb = new DbOnTheRocks(Path.Combine(_dbBasePath, DbOnTheRocks.BlocksDbPath)); var blockInfosDb = new DbOnTheRocks(Path.Combine(_dbBasePath, DbOnTheRocks.BlockInfosDbPath)); var receiptsDb = new DbOnTheRocks(Path.Combine(_dbBasePath, DbOnTheRocks.ReceiptsDbPath)); /* blockchain */ var blockTree = new BlockTree(blocksDb, blockInfosDb, receiptsDb, specProvider, _logManager); var difficultyCalculator = new DifficultyCalculator(specProvider); /* validation */ var headerValidator = new HeaderValidator(difficultyCalculator, blockTree, sealEngine, specProvider, _logManager); var ommersValidator = new OmmersValidator(blockTree, headerValidator, _logManager); var txValidator = new TransactionValidator(new SignatureValidator(specProvider.ChainId)); var blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, _logManager); /* state */ var dbProvider = new RocksDbProvider(_dbBasePath, _logManager); var codeDb = new DbOnTheRocks(Path.Combine(_dbBasePath, DbOnTheRocks.CodeDbPath)); var stateDb = new DbOnTheRocks(Path.Combine(_dbBasePath, DbOnTheRocks.StateDbPath)); var stateTree = new StateTree(stateDb); var stateProvider = new StateProvider(stateTree, codeDb, _logManager); var storageProvider = new StorageProvider(dbProvider, stateProvider, _logManager); /* blockchain processing */ var blockhashProvider = new BlockhashProvider(blockTree); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, _tracer, _logManager); var rewardCalculator = new RewardCalculator(specProvider); var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, transactionProcessor, dbProvider, stateProvider, storageProvider, transactionStore, _logManager); _blockchainProcessor = new BlockchainProcessor(blockTree, sealEngine, transactionStore, difficultyCalculator, blockProcessor, ethereumSigner, _logManager); // create shared objects between discovery and peer manager _nodeFactory = new NodeFactory(); _nodeStatsProvider = new NodeStatsProvider(_configProvider); var jsonSerializer = new JsonSerializer(_logManager); var encrypter = new AesEncrypter(_configProvider, _logManager); _keyStore = new FileKeyStore(_configProvider, jsonSerializer, encrypter, _cryptoRandom, _logManager); //creating blockchain bridge BlockchainBridge = new BlockchainBridge(ethereumSigner, stateProvider, _keyStore, blockTree, stateDb, transactionStore); EthereumSigner = ethereumSigner; _blockchainProcessor.Start(); LoadGenesisBlock(chainSpec, string.IsNullOrWhiteSpace(initParams.GenesisHash) ? null : new Keccak(initParams.GenesisHash), blockTree, stateProvider, specProvider); await StartProcessing(blockTree, transactionStore, blockValidator, headerValidator, txValidator, initParams); }
private static void InitBlockchain(ChainSpec chainSpec, bool isMining, int miningDelay) { /* spec */ var blockMiningTime = TimeSpan.FromMilliseconds(miningDelay); var transactionDelay = TimeSpan.FromMilliseconds(miningDelay / 4); var specProvider = RopstenSpecProvider.Instance; var difficultyCalculator = new DifficultyCalculator(specProvider); // var sealEngine = new EthashSealEngine(new Ethash()); var sealEngine = new FakeSealEngine(blockMiningTime, false); /* sync */ var transactionStore = new TransactionStore(); var blockTree = new BlockTree(RopstenSpecProvider.Instance, ChainLogger); /* validation */ var headerValidator = new HeaderValidator(difficultyCalculator, blockTree, sealEngine, specProvider, ChainLogger); var ommersValidator = new OmmersValidator(blockTree, headerValidator, ChainLogger); var txValidator = new TransactionValidator(new SignatureValidator(ChainId.Ropsten)); var blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, ChainLogger); /* state */ var dbProvider = new DbProvider(StateLogger); var codeDb = new InMemoryDb(); var stateDb = new InMemoryDb(); var stateTree = new StateTree(stateDb); var stateProvider = new StateProvider(stateTree, StateLogger, codeDb); var storageProvider = new StorageProvider(dbProvider, stateProvider, StateLogger); var storageDbProvider = new DbProvider(StateLogger); /* blockchain */ var ethereumSigner = new EthereumSigner(specProvider, ChainLogger); /* blockchain processing */ var blockhashProvider = new BlockhashProvider(blockTree); var virtualMachine = new VirtualMachine(specProvider, stateProvider, storageProvider, blockhashProvider, EvmLogger); var transactionProcessor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, ethereumSigner, ChainLogger); var rewardCalculator = new RewardCalculator(specProvider); var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, transactionProcessor, storageDbProvider, stateProvider, storageProvider, transactionStore, ChainLogger); _blockchainProcessor = new BlockchainProcessor(blockTree, sealEngine, transactionStore, difficultyCalculator, blockProcessor, ChainLogger); /* genesis */ foreach (KeyValuePair <Address, BigInteger> allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value); } stateProvider.Commit(specProvider.GenesisSpec); var testTransactionsGenerator = new TestTransactionsGenerator(transactionStore, ethereumSigner, transactionDelay, ChainLogger); stateProvider.CreateAccount(testTransactionsGenerator.SenderAddress, 1000.Ether()); stateProvider.Commit(specProvider.GenesisSpec); if (isMining) { testTransactionsGenerator.Start(); } Block genesis = chainSpec.Genesis; genesis.Header.StateRoot = stateProvider.StateRoot; genesis.Header.RecomputeHash(); // we are adding test transactions account so the state root will change (not an actual ropsten at the moment) // var expectedGenesisHash = "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"; // if (chainSpec.Genesis.Hash != new Keccak(expectedGenesisHash)) // { // throw new Exception($"Unexpected genesis hash for Ropsten, expected {expectedGenesisHash}, but was {chainSpec.Genesis.Hash}"); // } /* start test processing */ sealEngine.IsMining = isMining; _blockchainProcessor.Start(); blockTree.AddBlock(genesis); _syncManager = new SynchronizationManager( blockTree, blockValidator, headerValidator, transactionStore, txValidator, NetworkLogger); _syncManager.Start(); }
public void _Test_storage_failed_case(string historicallyFailingCase) { string[] lines = historicallyFailingCase.Split(Environment.NewLine); int storageCount = lines.Length - 2; IDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, LimboLogs.Instance); StateTree tree = new StateTree(trieStore, LimboLogs.Instance); Address address = new Address(Bytes.FromHexString(lines[0])); int accountIndex = int.Parse(lines[1]); UInt256[] indexes = new UInt256[storageCount]; for (int j = 0; j < storageCount; j++) { indexes[j] = UInt256.Parse(lines[j + 2].Replace("storage: ", string.Empty)); } AddressWithStorage addressWithStorage = new AddressWithStorage(); addressWithStorage.StorageCells = new StorageCell[storageCount]; addressWithStorage.Address = address; StorageTree storageTree = new StorageTree(trieStore, Keccak.EmptyTreeHash, LimboLogs.Instance); for (int j = 0; j < storageCount; j++) { UInt256 index = UInt256.Parse(lines[j + 2].Replace("storage: ", string.Empty)); StorageCell storageCell = new StorageCell(address, index); addressWithStorage.StorageCells[j] = storageCell; byte[] rawKey = new byte[32]; addressWithStorage.StorageCells[j].Index.ToBigEndian(rawKey); TestContext.WriteLine($"Set {Keccak.Compute(rawKey).Bytes.ToHexString()}"); storageTree.Set(addressWithStorage.StorageCells[j].Index, new byte[] { 1 }); storageTree.UpdateRootHash(); storageTree.Commit(0); } Account account = Build.An.Account.WithBalance((UInt256)accountIndex).WithStorageRoot(storageTree.RootHash).TestObject; tree.Set(addressWithStorage.Address, account); tree.UpdateRootHash(); tree.Commit(0); TreeDumper treeDumper = new TreeDumper(); tree.Accept(treeDumper, tree.RootHash, true); TestContext.WriteLine(treeDumper.ToString()); AccountProofCollector collector = new AccountProofCollector(address, indexes); tree.Accept(collector, tree.RootHash, true); AccountProof accountProof = collector.BuildResult(); accountProof.Address.Should().Be(address); accountProof.Balance.Should().Be((UInt256)accountIndex); accountProof.Nonce.Should().Be(0); accountProof.CodeHash.Should().Be(Keccak.OfAnEmptyString); if (accountIndex != 0) { accountProof.StorageRoot.Should().NotBe(Keccak.EmptyTreeHash); } accountProof.StorageProofs.Length.Should().Be(accountIndex); for (int j = 0; j < accountProof.StorageProofs.Length; j++) { TrieNode node = new TrieNode(NodeType.Unknown, accountProof.StorageProofs[j].Proof.Last()); node.ResolveNode(new TrieStore(memDb, NullLogManager.Instance)); if (node.Value.Length != 1) { TestContext.WriteLine($"{j}"); // throw new InvalidDataException($"{j}"); } } }
public PastState(StateTree stateTree, DateTime timestamp, object action) { this.stateTree = (StateTree)stateTree.Clone(); this.timestamp = timestamp; this.action = action; }
private async Task InitBlockchain() { /* spec */ if (_chainSpec.ChainId == RopstenSpecProvider.Instance.ChainId) { _specProvider = RopstenSpecProvider.Instance; } else if (_chainSpec.ChainId == MainNetSpecProvider.Instance.ChainId) { _specProvider = MainNetSpecProvider.Instance; } else if (_chainSpec.ChainId == RinkebySpecProvider.Instance.ChainId) { _specProvider = RinkebySpecProvider.Instance; } else if (_chainSpec.ChainId == GoerliSpecProvider.Instance.ChainId) { _specProvider = GoerliSpecProvider.Instance; } else if (_chainSpec.ChainId == SturebySpecProvider.Instance.ChainId) { _specProvider = SturebySpecProvider.Instance; } else { _specProvider = new SingleReleaseSpecProvider(LatestRelease.Instance, _chainSpec.ChainId); } /* sync */ IDbConfig dbConfig = _configProvider.GetConfig <IDbConfig>(); foreach (PropertyInfo propertyInfo in typeof(IDbConfig).GetProperties()) { _logger.Info($"DB {propertyInfo.Name}: {propertyInfo.GetValue(dbConfig)}"); } _dbProvider = HiveEnabled ? (IDbProvider) new MemDbProvider() : new RocksDbProvider(_initConfig.BaseDbPath, dbConfig, _logManager); _ethereumSigner = new EthereumSigner(_specProvider, _logManager); _transactionPool = new TransactionPool( new PersistentTransactionStorage(_dbProvider.PendingTxsDb, _specProvider), new PendingTransactionThresholdValidator(_initConfig.ObsoletePendingTransactionInterval, _initConfig.RemovePendingTransactionInterval), new Timestamp(), _ethereumSigner, _logManager, _initConfig.RemovePendingTransactionInterval, _initConfig.PeerNotificationThreshold); _receiptStorage = new PersistentReceiptStorage(_dbProvider.ReceiptsDb, _specProvider); // IDbProvider debugRecorder = new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig); // _dbProvider = new RpcDbProvider(_jsonSerializer, new BasicJsonRpcClient(KnownRpcUris.NethVm1, _jsonSerializer, _logManager), _logManager, debugRecorder); // IDbProvider debugReader = new ReadOnlyDbProvider(new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig)); // _dbProvider = debugReader; /* blockchain */ _blockTree = new BlockTree( _dbProvider.BlocksDb, _dbProvider.BlockInfosDb, _specProvider, _transactionPool, _logManager); var cliqueConfig = new CliqueConfig(15, 30000); var clique = new CliqueSealEngine(cliqueConfig, _ethereumSigner, _nodeKey, _dbProvider.BlocksDb, _blockTree, _logManager); clique.CanSeal = _initConfig.IsMining; // TODO: read seal engine from ChainSpec _sealEngine = (_specProvider is MainNetSpecProvider) ? ConfigureSealEngine() : (_specProvider is RopstenSpecProvider) ? ConfigureSealEngine() : (_specProvider is SturebySpecProvider) ? ConfigureSealEngine() : (_specProvider is RinkebySpecProvider) ? clique : (_specProvider is GoerliSpecProvider) ? (ISealEngine)clique : NullSealEngine.Instance; _rewardCalculator = (_sealEngine is CliqueSealEngine) ? (IRewardCalculator) new NoBlockRewards() : new RewardCalculator(_specProvider); /* validation */ var headerValidator = new HeaderValidator( _blockTree, _sealEngine, _specProvider, _logManager); var ommersValidator = new OmmersValidator( _blockTree, headerValidator, _logManager); var txValidator = new TransactionValidator( new SignatureValidator(_specProvider.ChainId)); _blockValidator = new BlockValidator( txValidator, headerValidator, ommersValidator, _specProvider, _logManager); var stateTree = new StateTree(_dbProvider.StateDb); var stateProvider = new StateProvider( stateTree, _dbProvider.CodeDb, _logManager); _stateProvider = stateProvider; var storageProvider = new StorageProvider( _dbProvider.StateDb, stateProvider, _logManager); _transactionPoolInfoProvider = new TransactionPoolInfoProvider(stateProvider); /* blockchain processing */ var blockhashProvider = new BlockhashProvider( _blockTree); var virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor( _specProvider, stateProvider, storageProvider, virtualMachine, _logManager); var txRecoveryStep = new TxSignaturesRecoveryStep(_ethereumSigner, _transactionPool); _recoveryStep = _sealEngine is CliqueSealEngine ? new CompositeDataRecoveryStep(txRecoveryStep, new AuthorRecoveryStep(clique)) : (IBlockDataRecoveryStep)txRecoveryStep; _blockProcessor = new BlockProcessor( _specProvider, _blockValidator, _rewardCalculator, transactionProcessor, _dbProvider.StateDb, _dbProvider.CodeDb, _dbProvider.TraceDb, stateProvider, storageProvider, _transactionPool, _receiptStorage, _logManager); _blockchainProcessor = new BlockchainProcessor( _blockTree, _blockProcessor, _recoveryStep, _logManager, true, true); // create shared objects between discovery and peer manager _nodeFactory = new NodeFactory(_logManager); _nodeStatsProvider = new NodeStatsProvider(_configProvider.GetConfig <IStatsConfig>(), _nodeFactory, _logManager); var jsonSerializer = new JsonSerializer( _logManager); var encrypter = new AesEncrypter( _configProvider, _logManager); _keyStore = new FileKeyStore( _configProvider, jsonSerializer, encrypter, _cryptoRandom, _logManager); if (_initConfig.IsMining) { IReadOnlyDbProvider minerDbProvider = new ReadOnlyDbProvider(_dbProvider, false); AlternativeChain producerChain = new AlternativeChain(_blockTree, _blockValidator, _rewardCalculator, _specProvider, minerDbProvider, _recoveryStep, _logManager, _transactionPool, _receiptStorage); if (_sealEngine is CliqueSealEngine engine) { // TODO: need to introduce snapshot provider for clique and pass it here instead of CliqueSealEngine if (_logger.IsWarn) { _logger.Warn("Starting Clique block producer & sealer"); } _blockProducer = new CliqueBlockProducer(_transactionPool, producerChain.Processor, _blockTree, producerChain.StateProvider, _timestamp, _cryptoRandom, engine, cliqueConfig, _nodeKey.Address, _logManager); } else { if (_logger.IsWarn) { _logger.Warn("Starting Dev block producer & sealer"); } _blockProducer = new DevBlockProducer(_transactionPool, producerChain.Processor, _blockTree, _timestamp, _logManager); } _blockProducer.Start(); } if (!HiveEnabled) { _blockchainProcessor.Start(); LoadGenesisBlock(_chainSpec, string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Keccak(_initConfig.GenesisHash), _blockTree, stateProvider, _specProvider); if (_initConfig.ProcessingEnabled) { #pragma warning disable 4014 LoadBlocksFromDb(); #pragma warning restore 4014 } else { if (_logger.IsWarn) { _logger.Warn($"Shutting down processor due to {nameof(InitConfig)}.{nameof(InitConfig.ProcessingEnabled)} set to false"); } await _blockchainProcessor.StopAsync(); } } await InitializeNetwork( _receiptStorage, headerValidator, txValidator); }
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"); }
private async Task InitBlockchain() { ChainSpec chainSpec = LoadChainSpec(_initConfig.ChainSpecPath); /* spec */ // TODO: rebuild to use chainspec ISpecProvider specProvider; if (chainSpec.ChainId == RopstenSpecProvider.Instance.ChainId) { specProvider = RopstenSpecProvider.Instance; } else if (chainSpec.ChainId == MainNetSpecProvider.Instance.ChainId) { specProvider = MainNetSpecProvider.Instance; } else { throw new NotSupportedException($"Not yet tested, not yet supported ChainId {chainSpec.ChainId}"); } var ethereumSigner = new EthereumSigner( specProvider, _logManager); var transactionStore = new TransactionStore(); var sealEngine = ConfigureSealEngine( transactionStore, ethereumSigner); /* sync */ IDbConfig dbConfig = _configProvider.GetConfig <IDbConfig>(); foreach (PropertyInfo propertyInfo in typeof(IDbConfig).GetProperties()) { _logger.Info($"DB {propertyInfo.Name}: {propertyInfo.GetValue(dbConfig)}"); } var blocksDb = new DbOnTheRocks( Path.Combine(_dbBasePath, DbOnTheRocks.BlocksDbPath), dbConfig); var blockInfosDb = new DbOnTheRocks( Path.Combine(_dbBasePath, DbOnTheRocks.BlockInfosDbPath), dbConfig); var receiptsDb = new DbOnTheRocks( Path.Combine(_dbBasePath, DbOnTheRocks.ReceiptsDbPath), dbConfig); /* blockchain */ _blockTree = new BlockTree( blocksDb, blockInfosDb, receiptsDb, specProvider, _logManager); var difficultyCalculator = new DifficultyCalculator( specProvider); /* validation */ var headerValidator = new HeaderValidator( difficultyCalculator, _blockTree, sealEngine, specProvider, _logManager); var ommersValidator = new OmmersValidator( _blockTree, headerValidator, _logManager); var txValidator = new TransactionValidator( new SignatureValidator(specProvider.ChainId)); var blockValidator = new BlockValidator( txValidator, headerValidator, ommersValidator, specProvider, _logManager); /* state */ var dbProvider = new RocksDbProvider( _dbBasePath, _logManager, dbConfig); var stateDb = dbProvider.GetOrCreateStateDb(); var stateTree = new StateTree(stateDb); var stateProvider = new StateProvider( stateTree, dbProvider.GetOrCreateCodeDb(), _logManager); var storageProvider = new StorageProvider( dbProvider, stateProvider, _logManager); /* blockchain processing */ var blockhashProvider = new BlockhashProvider( _blockTree); var virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor( specProvider, stateProvider, storageProvider, virtualMachine, _tracer, _logManager); var rewardCalculator = new RewardCalculator( specProvider); var blockProcessor = new BlockProcessor( specProvider, blockValidator, rewardCalculator, transactionProcessor, dbProvider, stateProvider, storageProvider, transactionStore, _logManager); _blockchainProcessor = new BlockchainProcessor( _blockTree, sealEngine, transactionStore, difficultyCalculator, blockProcessor, ethereumSigner, _logManager, _perfService); // create shared objects between discovery and peer manager _nodeFactory = new NodeFactory(); _nodeStatsProvider = new NodeStatsProvider(_configProvider.GetConfig <IStatsConfig>(), _nodeFactory, _logManager); var jsonSerializer = new JsonSerializer( _logManager); var encrypter = new AesEncrypter( _configProvider, _logManager); _keyStore = new FileKeyStore( _configProvider, jsonSerializer, encrypter, _cryptoRandom, _logManager); //creating blockchain bridge BlockchainBridge = new BlockchainBridge( ethereumSigner, stateProvider, _keyStore, _blockTree, stateDb, transactionStore); EthereumSigner = ethereumSigner; _blockchainProcessor.Start(); LoadGenesisBlock(chainSpec, string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Keccak(_initConfig.GenesisHash), _blockTree, stateProvider, specProvider); #pragma warning disable 4014 LoadBlocksFromDb(); #pragma warning restore 4014 await InitializeNetwork( transactionStore, blockValidator, headerValidator, txValidator); }
public Account GetAccount(Address address, Keccak stateRoot) { var stateTree = new StateTree(_db, stateRoot); return(stateTree.Get(address)); }
protected async Task RunTest(BlockchainTest test, Stopwatch stopwatch = null) { Assert.IsNull(test.LoadFailure, "test data loading failure"); // TODO: not supported in .NET Core, need to replace? // LoggingTraceListener traceListener = new LoggingTraceListener(); // Debug.Listeners.Clear(); // Debug.Listeners.Add(traceListener); ISnapshotableDb stateDb = new StateDb(); ISnapshotableDb codeDb = new StateDb(); IDb traceDb = new MemDb(); StateTree stateTree = new StateTree(stateDb); ISpecProvider specProvider; if (test.NetworkAfterTransition != null) { specProvider = new CustomSpecProvider( (0, Frontier.Instance), (1, test.Network), (test.TransitionBlockNumber, test.NetworkAfterTransition)); } else { specProvider = new CustomSpecProvider( (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); IEthereumSigner signer = new EthereumSigner(specProvider, _logManager); ITransactionPool transactionPool = new TransactionPool(NullTransactionStorage.Instance, new PendingTransactionThresholdValidator(), new Timestamp(), signer, _logManager); IReceiptStorage receiptStorage = NullReceiptStorage.Instance; IBlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), specProvider, transactionPool, _logManager); IBlockhashProvider blockhashProvider = new BlockhashProvider(blockTree); ISignatureValidator signatureValidator = new SignatureValidator(ChainId.MainNet); ITransactionValidator transactionValidator = new TransactionValidator(signatureValidator); IHeaderValidator headerValidator = new HeaderValidator(blockTree, SealEngine, specProvider, _logManager); IOmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, _logManager); IBlockValidator blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, _logManager); IStateProvider stateProvider = new StateProvider(stateTree, codeDb, _logManager); IStorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, _logManager); IVirtualMachine virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); IBlockProcessor blockProcessor = new BlockProcessor( specProvider, blockValidator, rewardCalculator, new TransactionProcessor( specProvider, stateProvider, storageProvider, virtualMachine, _logManager), stateDb, codeDb, traceDb, stateProvider, storageProvider, transactionPool, receiptStorage, _logManager); IBlockchainProcessor blockchainProcessor = new BlockchainProcessor( blockTree, blockProcessor, new TxSignaturesRecoveryStep(signer, NullTransactionPool.Instance), _logManager, false, false); InitializeTestState(test, stateProvider, storageProvider, specProvider); List <(Block Block, string ExpectedException)> correctRlpsBlocks = new List <(Block, string)>(); for (int i = 0; i < test.Blocks.Length; i++) { try { TestBlockJson testBlockJson = test.Blocks[i]; var rlpContext = Bytes.FromHexString(testBlockJson.Rlp).AsRlpContext(); 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"); } correctRlpsBlocks.Add((suggestedBlock, testBlockJson.ExpectedException)); } catch (Exception) { _logger?.Info($"Invalid RLP ({i})"); } } if (correctRlpsBlocks.Count == 0) { Assert.AreEqual(new Keccak(test.GenesisBlockHeader.Hash), test.LastBlockHash); return; } if (test.GenesisRlp == null) { test.GenesisRlp = Rlp.Encode(new Block(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 ManualResetEvent(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 0) { Assert.AreEqual(genesisBlock.Header.StateRoot, stateTree.RootHash, "genesis state root"); genesisProcessed.Set(); } }; blockchainProcessor.Start(); blockTree.SuggestBlock(genesisBlock); genesisProcessed.WaitOne(); for (int i = 0; i < correctRlpsBlocks.Count; i++) { stopwatch?.Start(); try { if (correctRlpsBlocks[i].ExpectedException != null) { _logger.Info($"Expecting block exception: {correctRlpsBlocks[i].ExpectedException}"); } if (correctRlpsBlocks[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(correctRlpsBlocks[i].Block)) { blockTree.SuggestBlock(correctRlpsBlocks[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"); }
private void button1_Click_1(object sender, EventArgs e) { char test = 'a'; StateTree<string> tree = new StateTree<string>(EqualityComparer<string>.Default); for (int i=0; i<26; i++) { char test2 = (char)(test + i); tree.AddState(test2.ToString()); } MessageBox.Show(String.Join(",",tree.GetLevel0Children("a", 3))); MessageBox.Show(String.Join(",",tree.GetChildren("a", 3))); }
public void Chaotic_test() { const int accountsCount = 100; CryptoRandom random = new CryptoRandom(); List <AddressWithStorage> addressesWithStorage = new List <AddressWithStorage>(); for (int i = 0; i < accountsCount; i++) { AddressWithStorage addressWithStorage = new AddressWithStorage(); addressWithStorage.StorageCells = new StorageCell[i]; byte[] addressBytes = random.GenerateRandomBytes(20); addressWithStorage.Address = new Address(addressBytes); for (int j = 0; j < i; j++) { byte[] storageIndex = random.GenerateRandomBytes(32); UInt256 index = new UInt256(storageIndex); StorageCell storageCell = new StorageCell(addressWithStorage.Address, index); addressWithStorage.StorageCells[j] = storageCell; } addressesWithStorage.Add(addressWithStorage); } IDb memDb = new MemDb(); TrieStore trieStore = new TrieStore(memDb, LimboLogs.Instance); StateTree tree = new StateTree(trieStore, LimboLogs.Instance); for (int i = 0; i < accountsCount; i++) { Account account = Build.An.Account.WithBalance((UInt256)i).TestObject; StorageTree storageTree = new StorageTree(trieStore, Keccak.EmptyTreeHash, LimboLogs.Instance); for (int j = 0; j < i; j++) { storageTree.Set(addressesWithStorage[i].StorageCells[j].Index, new byte[1] { 1 }); } storageTree.UpdateRootHash(); storageTree.Commit(0); account = account.WithChangedStorageRoot(storageTree.RootHash); tree.Set(addressesWithStorage[i].Address, account); } tree.UpdateRootHash(); tree.Commit(0); for (int i = 0; i < accountsCount; i++) { AccountProofCollector collector = new AccountProofCollector(addressesWithStorage[i].Address, addressesWithStorage[i].StorageCells.Select(sc => sc.Index).ToArray()); tree.Accept(collector, tree.RootHash, true); AccountProof accountProof = collector.BuildResult(); accountProof.Address.Should().Be(addressesWithStorage[i].Address); accountProof.Balance.Should().Be((UInt256)i); accountProof.Nonce.Should().Be(0); accountProof.CodeHash.Should().Be(Keccak.OfAnEmptyString); if (i != 0) { accountProof.StorageRoot.Should().NotBe(Keccak.EmptyTreeHash); } accountProof.StorageProofs.Length.Should().Be(i); for (int j = 0; j < i; j++) { byte[] indexBytes = new byte[32]; addressesWithStorage[i].StorageCells[j].Index.ToBigEndian(indexBytes.AsSpan()); accountProof.StorageProofs[j].Key.ToHexString().Should().Be(indexBytes.ToHexString(), $"{i} {j}"); TrieNode node = new TrieNode(NodeType.Unknown, accountProof.StorageProofs[j].Proof.Last()); node.ResolveNode(null); // TestContext.Write($"|[{i},{j}]"); if (node.Value.Length != 1) { TestContext.WriteLine(); TestContext.WriteLine(addressesWithStorage[i].Address); TestContext.WriteLine(i); foreach (StorageCell storageCell in addressesWithStorage[i].StorageCells) { TestContext.WriteLine("storage: " + storageCell.Index); } } node.Value.Should().BeEquivalentTo(new byte[] { 1 }); } } }
protected async Task RunTest(BlockchainTest test, Stopwatch stopwatch = null) { LoggingTraceListener traceListener = new LoggingTraceListener(); // TODO: not supported in .NET Core, need to replace? // Debug.Listeners.Clear(); // Debug.Listeners.Add(traceListener); IDbProvider dbProvider = new MemDbProvider(_logManager); StateTree stateTree = new StateTree(dbProvider.GetOrCreateStateDb()); ISpecProvider specProvider; if (test.NetworkAfterTransition != null) { specProvider = new CustomSpecProvider( (0, Frontier.Instance), (1, test.Network), (test.TransitionBlockNumber, test.NetworkAfterTransition)); } else { specProvider = new CustomSpecProvider( (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"); } IDifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); IRewardCalculator rewardCalculator = new RewardCalculator(specProvider); IBlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), specProvider, _logManager); IBlockhashProvider blockhashProvider = new BlockhashProvider(blockTree); ISignatureValidator signatureValidator = new SignatureValidator(ChainId.MainNet); ITransactionValidator transactionValidator = new TransactionValidator(signatureValidator); IHeaderValidator headerValidator = new HeaderValidator(difficultyCalculator, blockTree, SealEngine, specProvider, _logManager); IOmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, _logManager); IBlockValidator blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, _logManager); IStateProvider stateProvider = new StateProvider(stateTree, dbProvider.GetOrCreateCodeDb(), _logManager); IStorageProvider storageProvider = new StorageProvider(dbProvider, stateProvider, _logManager); IVirtualMachine virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); ISealEngine sealEngine = new EthashSealEngine(new Ethash(_logManager), _logManager); ITransactionStore transactionStore = new TransactionStore(); IEthereumSigner signer = new EthereumSigner(specProvider, _logManager); IBlockProcessor blockProcessor = new BlockProcessor( specProvider, blockValidator, rewardCalculator, new TransactionProcessor( specProvider, stateProvider, storageProvider, virtualMachine, NullTracer.Instance, _logManager), dbProvider, stateProvider, storageProvider, transactionStore, _logManager); IBlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, sealEngine, transactionStore, difficultyCalculator, blockProcessor, signer, _logManager); InitializeTestState(test, stateProvider, storageProvider, specProvider); List <(Block Block, string ExpectedException)> correctRlpsBlocks = new List <(Block, string)>(); for (int i = 0; i < test.Blocks.Length; i++) { try { TestBlockJson testBlockJson = test.Blocks[i]; var rlpContext = Hex.ToBytes(testBlockJson.Rlp).AsRlpContext(); Block suggestedBlock = Rlp.Decode <Block>(rlpContext); 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"); } correctRlpsBlocks.Add((suggestedBlock, testBlockJson.ExpectedException)); } catch (Exception e) { _logger?.Info($"Invalid RLP ({i})"); } } if (correctRlpsBlocks.Count == 0) { Assert.AreEqual(new Keccak(test.GenesisBlockHeader.Hash), test.LastBlockHash); return; } if (test.GenesisRlp == null) { test.GenesisRlp = Rlp.Encode(new Block(Convert(test.GenesisBlockHeader))); } Block genesisBlock = Rlp.Decode <Block>(test.GenesisRlp.Bytes); Assert.AreEqual(new Keccak(test.GenesisBlockHeader.Hash), genesisBlock.Header.Hash, "genesis header hash"); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 0) { Assert.AreEqual(genesisBlock.Header.StateRoot, stateTree.RootHash, "genesis state root"); } }; blockchainProcessor.Start(); blockTree.SuggestBlock(genesisBlock); for (int i = 0; i < correctRlpsBlocks.Count; i++) { stopwatch?.Start(); try { if (correctRlpsBlocks[i].ExpectedException != null) { _logger.Info($"Expecting block exception: {correctRlpsBlocks[i].ExpectedException}"); } if (correctRlpsBlocks[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 (blockValidator.ValidateSuggestedBlock(correctRlpsBlocks[i].Block)) { blockTree.SuggestBlock(correctRlpsBlocks[i].Block); } else { Console.WriteLine("Invalid block"); } } catch (InvalidBlockException ex) { } catch (Exception ex) { _logger?.Info(ex.ToString()); } } await blockchainProcessor.StopAsync(true); stopwatch?.Stop(); RunAssertions(test, blockTree.RetrieveHeadBlock(), storageProvider, stateProvider); }
private async Task InitBlockchain() { /* spec */ if (_chainSpec.ChainId == RopstenSpecProvider.Instance.ChainId) { _specProvider = RopstenSpecProvider.Instance; } else if (_chainSpec.ChainId == MainNetSpecProvider.Instance.ChainId) { _specProvider = MainNetSpecProvider.Instance; } else if (_chainSpec.ChainId == RinkebySpecProvider.Instance.ChainId) { _specProvider = RinkebySpecProvider.Instance; } else if (_chainSpec.ChainId == GoerliSpecProvider.Instance.ChainId) { _specProvider = GoerliSpecProvider.Instance; } else if (_chainSpec.ChainId == SturebySpecProvider.Instance.ChainId) { _specProvider = SturebySpecProvider.Instance; } else { _specProvider = new SingleReleaseSpecProvider(LatestRelease.Instance, _chainSpec.ChainId); } /* sync */ IDbConfig dbConfig = _configProvider.GetConfig <IDbConfig>(); foreach (PropertyInfo propertyInfo in typeof(IDbConfig).GetProperties()) { if (_logger.IsDebug) { _logger.Debug($"DB {propertyInfo.Name}: {propertyInfo.GetValue(dbConfig)}"); } } _dbProvider = HiveEnabled ? (IDbProvider) new MemDbProvider() : new RocksDbProvider(_initConfig.BaseDbPath, dbConfig, _logManager, _initConfig.StoreTraces, _initConfig.StoreReceipts); _ethereumEcdsa = new EthereumEcdsa(_specProvider, _logManager); _transactionPool = new TransactionPool( new PersistentTransactionStorage(_dbProvider.PendingTxsDb, _specProvider), new PendingTransactionThresholdValidator(_initConfig.ObsoletePendingTransactionInterval, _initConfig.RemovePendingTransactionInterval), new Timestamp(), _ethereumEcdsa, _specProvider, _logManager, _initConfig.RemovePendingTransactionInterval, _initConfig.PeerNotificationThreshold); _receiptStorage = new PersistentReceiptStorage(_dbProvider.ReceiptsDb, _specProvider); // IDbProvider debugRecorder = new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig); // _dbProvider = new RpcDbProvider(_jsonSerializer, new BasicJsonRpcClient(KnownRpcUris.NethVm1, _jsonSerializer, _logManager), _logManager, debugRecorder); // IDbProvider debugReader = new ReadOnlyDbProvider(new RocksDbProvider(Path.Combine(_dbBasePath, "debug"), dbConfig)); // _dbProvider = debugReader; _blockTree = new BlockTree( _dbProvider.BlocksDb, _dbProvider.BlockInfosDb, _specProvider, _transactionPool, _logManager); _recoveryStep = new TxSignaturesRecoveryStep(_ethereumEcdsa, _transactionPool); CliqueConfig cliqueConfig = null; _snapshotManager = null; switch (_chainSpec.SealEngineType) { case SealEngineType.None: _sealer = NullSealEngine.Instance; _sealValidator = NullSealEngine.Instance; _rewardCalculator = NoBlockRewards.Instance; break; case SealEngineType.Clique: _rewardCalculator = NoBlockRewards.Instance; cliqueConfig = new CliqueConfig(); cliqueConfig.BlockPeriod = _chainSpec.CliquePeriod; cliqueConfig.Epoch = _chainSpec.CliqueEpoch; _snapshotManager = new SnapshotManager(cliqueConfig, _dbProvider.BlocksDb, _blockTree, _ethereumEcdsa, _logManager); _sealValidator = new CliqueSealValidator(cliqueConfig, _snapshotManager, _logManager); _recoveryStep = new CompositeDataRecoveryStep(_recoveryStep, new AuthorRecoveryStep(_snapshotManager)); if (_initConfig.IsMining) { _sealer = new CliqueSealer(new BasicWallet(_nodeKey), cliqueConfig, _snapshotManager, _nodeKey.Address, _logManager); } else { _sealer = NullSealEngine.Instance; } break; case SealEngineType.NethDev: _sealer = NullSealEngine.Instance; _sealValidator = NullSealEngine.Instance; _rewardCalculator = NoBlockRewards.Instance; break; case SealEngineType.Ethash: _rewardCalculator = new RewardCalculator(_specProvider); var difficultyCalculator = new DifficultyCalculator(_specProvider); if (_initConfig.IsMining) { _sealer = new EthashSealer(new Ethash(_logManager), _logManager); } else { _sealer = NullSealEngine.Instance; } _sealValidator = new EthashSealValidator(_logManager, difficultyCalculator, new Ethash(_logManager)); break; default: throw new NotSupportedException($"Seal engine type {_chainSpec.SealEngineType} is not supported in Nethermind"); } /* validation */ var headerValidator = new HeaderValidator( _blockTree, _sealValidator, _specProvider, _logManager); var ommersValidator = new OmmersValidator( _blockTree, headerValidator, _logManager); var txValidator = new TransactionValidator( new SignatureValidator(_specProvider.ChainId)); _blockValidator = new BlockValidator( txValidator, headerValidator, ommersValidator, _specProvider, _logManager); var stateTree = new StateTree(_dbProvider.StateDb); var stateProvider = new StateProvider( stateTree, _dbProvider.CodeDb, _logManager); _stateProvider = stateProvider; var storageProvider = new StorageProvider( _dbProvider.StateDb, stateProvider, _logManager); _transactionPoolInfoProvider = new TransactionPoolInfoProvider(stateProvider); /* blockchain processing */ var blockhashProvider = new BlockhashProvider( _blockTree); var virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, _logManager); var transactionProcessor = new TransactionProcessor( _specProvider, stateProvider, storageProvider, virtualMachine, _logManager); _blockProcessor = new BlockProcessor( _specProvider, _blockValidator, _rewardCalculator, transactionProcessor, _dbProvider.StateDb, _dbProvider.CodeDb, _dbProvider.TraceDb, stateProvider, storageProvider, _transactionPool, _receiptStorage, _logManager); _blockchainProcessor = new BlockchainProcessor( _blockTree, _blockProcessor, _recoveryStep, _logManager, _initConfig.StoreReceipts, _initConfig.StoreTraces); // create shared objects between discovery and peer manager IStatsConfig statsConfig = _configProvider.GetConfig <IStatsConfig>(); _nodeStatsManager = new NodeStatsManager(statsConfig, _logManager, !statsConfig.CaptureNodeStatsEventHistory); if (_initConfig.IsMining) { IReadOnlyDbProvider minerDbProvider = new ReadOnlyDbProvider(_dbProvider, false); AlternativeChain producerChain = new AlternativeChain(_blockTree, _blockValidator, _rewardCalculator, _specProvider, minerDbProvider, _recoveryStep, _logManager, _transactionPool, _receiptStorage); switch (_chainSpec.SealEngineType) { case SealEngineType.Clique: { // TODO: need to introduce snapshot provider for clique and pass it here instead of CliqueSealEngine if (_logger.IsWarn) { _logger.Warn("Starting Clique block producer & sealer"); } _blockProducer = new CliqueBlockProducer(_transactionPool, producerChain.Processor, _blockTree, _timestamp, _cryptoRandom, producerChain.StateProvider, _snapshotManager, (CliqueSealer)_sealer, _nodeKey.Address, cliqueConfig, _logManager); break; } case SealEngineType.NethDev: { if (_logger.IsWarn) { _logger.Warn("Starting Dev block producer & sealer"); } _blockProducer = new DevBlockProducer(_transactionPool, producerChain.Processor, _blockTree, _timestamp, _logManager); break; } default: throw new NotSupportedException($"Mining in {_chainSpec.SealEngineType} mode is not supported"); } _blockProducer.Start(); } if (!HiveEnabled) { _blockchainProcessor.Start(); LoadGenesisBlock(_chainSpec, string.IsNullOrWhiteSpace(_initConfig.GenesisHash) ? null : new Keccak(_initConfig.GenesisHash), _blockTree, stateProvider, _specProvider); if (_initConfig.ProcessingEnabled) { #pragma warning disable 4014 LoadBlocksFromDb(); #pragma warning restore 4014 } else { if (_logger.IsWarn) { _logger.Warn($"Shutting down processor due to {nameof(InitConfig)}.{nameof(InitConfig.ProcessingEnabled)} set to false"); } await _blockchainProcessor.StopAsync(); } } await InitializeNetwork( _receiptStorage, _sealValidator, txValidator); }
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 */ FakeSealEngine sealEngine = new FakeSealEngine(miningDelay); sealEngine.CanSeal = true; RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; /* store & validation */ EthereumSigner ethereumSigner = new EthereumSigner(specProvider, logManager); MemDb receiptsDb = new MemDb(); MemDb traceDb = new MemDb(); TransactionPool transactionPool = new TransactionPool(new NullTransactionStorage(), new PendingTransactionThresholdValidator(), new Timestamp(), ethereumSigner, logManager); IReceiptStorage receiptStorage = new PersistentReceiptStorage(receiptsDb, specProvider); BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), specProvider, transactionPool, logManager); Timestamp timestamp = new Timestamp(); DifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); HeaderValidator headerValidator = new HeaderValidator(blockTree, sealEngine, specProvider, logManager); OmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, logManager); TransactionValidator transactionValidator = new TransactionValidator(new SignatureValidator(ChainId.Ropsten)); BlockValidator blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, logManager); /* state & storage */ StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); StateTree stateTree = new StateTree(stateDb); StateProvider stateProvider = new StateProvider(stateTree, codeDb, logManager); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, logManager); TestTransactionsGenerator generator = new TestTransactionsGenerator(transactionPool, ethereumSigner, TimeSpan.FromMilliseconds(5 * timeMultiplier), NullLogManager.Instance); generator.Start(); /* blockchain processing */ BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree); 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, transactionPool, receiptStorage, logManager); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ethereumSigner, NullTransactionPool.Instance), logManager, false, false); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new UnforgivingJsonSerializer()); 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); } 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, transactionPool, blockchainProcessor, sealEngine, blockTree, timestamp, NullLogManager.Instance); minedBlockProducer.Start(); ManualResetEvent manualResetEvent = new ManualResetEvent(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.WaitOne(miningDelay * 12 * timeMultiplier); await minedBlockProducer.StopAsync(); int previousCount = 0; int totalTx = 0; for (int i = 0; i < 6; i++) { Block block = blockTree.FindBlock(new UInt256(i)); logger.Info($"Block {i} with {block.Transactions.Length} txs"); ManualResetEvent blockProcessedEvent = new ManualResetEvent(false); blockchainProcessor.ProcessingQueueEmpty += (sender, args) => blockProcessedEvent.Set(); blockchainProcessor.SuggestBlock(block.Hash, ProcessingOptions.ForceProcessing | ProcessingOptions.StoreReceipts | ProcessingOptions.ReadOnlyChain); blockProcessedEvent.WaitOne(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 void Setup() { _inputTree = TestItem.Tree.GetStateTree(null); }
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); }); }