public static INdmBlockchainBridge BuildABridge()
        {
            MemDbProvider    memDbProvider    = new MemDbProvider();
            StateReader      stateReader      = new StateReader(memDbProvider.StateDb, memDbProvider.CodeDb, LimboLogs.Instance);
            StateProvider    stateProvider    = new StateProvider(memDbProvider.StateDb, memDbProvider.CodeDb, LimboLogs.Instance);
            IEthereumEcdsa   ecdsa            = new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance);
            ITxPool          txPool           = new TxPool.TxPool(new InMemoryTxStorage(), ecdsa, MainnetSpecProvider.Instance, new TxPoolConfig(), stateProvider, LimboLogs.Instance);
            BlockTree        blockTree        = Build.A.BlockTree().OfChainLength(1).TestObject;
            IWallet          wallet           = new DevWallet(new WalletConfig(), LimboLogs.Instance);
            ReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(ecdsa, MainnetSpecProvider.Instance);
            LogFinder        logFinder        = new LogFinder(blockTree, new InMemoryReceiptStorage(), NullBloomStorage.Instance, LimboLogs.Instance, receiptsRecovery, 1024);

            ReadOnlyTxProcessingEnv processingEnv = new ReadOnlyTxProcessingEnv(
                new ReadOnlyDbProvider(memDbProvider, false),
                new ReadOnlyBlockTree(blockTree),
                MainnetSpecProvider.Instance, LimboLogs.Instance);
            BlockchainBridge blockchainBridge = new BlockchainBridge(
                processingEnv,
                txPool,
                new InMemoryReceiptStorage(),
                NullFilterStore.Instance,
                NullFilterManager.Instance,
                ecdsa,
                Timestamper.Default,
                logFinder,
                false,
                false);

            WalletTxSigner txSigner  = new WalletTxSigner(wallet, ChainId.Mainnet);
            ITxSealer      txSealer0 = new TxSealer(txSigner, Timestamper.Default);
            ITxSealer      txSealer1 = new NonceReservingTxSealer(txSigner, Timestamper.Default, txPool);
            ITxSender      txSender  = new TxPoolSender(txPool, txSealer0, txSealer1);

            return(new NdmBlockchainBridge(blockchainBridge, blockTree, stateReader, txSender));
        }
        private void ResetMigrationIndexIfNeeded()
        {
            ReceiptsRecovery recovery = new ReceiptsRecovery();

            if (_receiptStorage.MigratedBlockNumber != long.MaxValue)
            {
                var blockNumber = _blockTree.Head?.Number ?? 0;
                while (blockNumber > 0)
                {
                    var level          = _chainLevelInfoRepository.LoadLevel(blockNumber);
                    var firstBlockInfo = level?.BlockInfos.FirstOrDefault();
                    if (firstBlockInfo != null)
                    {
                        var receipts = _receiptStorage.Get(firstBlockInfo.BlockHash);
                        if (receipts?.Length > 0)
                        {
                            if (recovery.NeedRecover(receipts))
                            {
                                _receiptStorage.MigratedBlockNumber = long.MaxValue;
                            }

                            break;
                        }
                    }

                    blockNumber--;
                }
            }
        }
Example #3
0
        private void ResetMigrationIndexIfNeeded()
        {
            ReceiptsRecovery recovery = new ReceiptsRecovery(_api.EthereumEcdsa, _api.SpecProvider);

            if (_receiptStorage.MigratedBlockNumber != long.MaxValue)
            {
                long blockNumber = _blockTree.Head?.Number ?? 0;
                while (blockNumber > 0)
                {
                    ChainLevelInfo?level          = _chainLevelInfoRepository.LoadLevel(blockNumber);
                    BlockInfo?     firstBlockInfo = level?.BlockInfos.FirstOrDefault();
                    if (firstBlockInfo != null)
                    {
                        TxReceipt[] receipts = _receiptStorage.Get(firstBlockInfo.BlockHash);
                        if (receipts.Length > 0)
                        {
                            if (recovery.NeedRecover(receipts))
                            {
                                _receiptStorage.MigratedBlockNumber = long.MaxValue;
                            }

                            break;
                        }
                    }

                    blockNumber--;
                }
            }
        }
Example #4
0
        public Task Execute(CancellationToken cancellationToken)
        {
            IInitConfig  initConfig  = _get.Config <IInitConfig>();
            IBloomConfig bloomConfig = _get.Config <IBloomConfig>();

            IFileStoreFactory fileStoreFactory = initConfig.DiagnosticMode == DiagnosticMode.MemDb
                ? (IFileStoreFactory) new InMemoryDictionaryFileStoreFactory()
                : new FixedSizeFileStoreFactory(Path.Combine(initConfig.BaseDbPath, DbNames.Bloom), DbNames.Bloom, Bloom.ByteLength);

            var bloomStorage =
                _set.BloomStorage = bloomConfig.Index
                    ? new BloomStorage(bloomConfig, _get.DbProvider !.BloomDb, fileStoreFactory)
                    : (IBloomStorage)NullBloomStorage.Instance;

            _get.DisposeStack.Push(bloomStorage);

            var chainLevelInfoRepository =
                _set.ChainLevelInfoRepository = new ChainLevelInfoRepository(_get.DbProvider !.BlockInfosDb);

            var blockTree = _set.BlockTree = new BlockTree(
                _get.DbProvider,
                chainLevelInfoRepository,
                _get.SpecProvider,
                bloomStorage,
                _get.Config <ISyncConfig>(),
                _get.LogManager);

            ISigner      signer      = NullSigner.Instance;
            ISignerStore signerStore = NullSigner.Instance;

            if (_get.Config <IMiningConfig>().Enabled)
            {
                Signer signerAndStore = new Signer(_get.SpecProvider !.ChainId, _get.OriginalSignerKey, _get.LogManager);
                signer      = signerAndStore;
                signerStore = signerAndStore;
            }

            _set.EngineSigner      = signer;
            _set.EngineSignerStore = signerStore;

            ReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(_get.EthereumEcdsa, _get.SpecProvider);
            var receiptStorage = _set.ReceiptStorage
                                     = initConfig.StoreReceipts ? (IReceiptStorage?)new PersistentReceiptStorage(_get.DbProvider.ReceiptsDb, _get.SpecProvider, receiptsRecovery) : NullReceiptStorage.Instance;
            var receiptFinder = _set.ReceiptFinder = new FullInfoReceiptFinder(receiptStorage, receiptsRecovery, blockTree);

            LogFinder logFinder = new LogFinder(
                blockTree,
                receiptFinder,
                bloomStorage,
                _get.LogManager,
                new ReceiptsRecovery(_get.EthereumEcdsa, _get.SpecProvider),
                1024);

            _set.LogFinder = logFinder;

            return(Task.CompletedTask);
        }
        public void Setup()
        {
            _specProvider  = RopstenSpecProvider.Instance;
            _ethereumEcdsa = new EthereumEcdsa(_specProvider.ChainId, LimboLogs.Instance);
            ReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(_ethereumEcdsa, _specProvider);

            _persistentStorage = new PersistentReceiptStorage(new MemColumnsDb <ReceiptsColumns>(), _specProvider, receiptsRecovery);
            _inMemoryStorage   = new InMemoryReceiptStorage();
        }
        public void SetUp()
        {
            var specProvider  = RopstenSpecProvider.Instance;
            var ethereumEcdsa = new EthereumEcdsa(specProvider.ChainId, LimboLogs.Instance);
            ReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(ethereumEcdsa, specProvider);

            _receiptsDb = new MemColumnsDb <ReceiptsColumns>();
            _storage    = new PersistentReceiptStorage(_receiptsDb, MainnetSpecProvider.Instance, receiptsRecovery)
            {
                MigratedBlockNumber = 0
            };
            _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks).Set(Keccak.Zero, Array.Empty <byte>());
        }
        public static INdmBlockchainBridge BuildABridge()
        {
            IDbProvider memDbProvider = TestMemDbProvider.Init();
            StateReader stateReader   = new StateReader(
                new TrieStore(memDbProvider.StateDb, LimboLogs.Instance), memDbProvider.CodeDb, LimboLogs.Instance);
            var                          trieStore     = new TrieStore(memDbProvider.StateDb, LimboLogs.Instance);
            StateProvider                stateProvider = new StateProvider(trieStore, memDbProvider.CodeDb, LimboLogs.Instance);
            IEthereumEcdsa               ecdsa         = new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance);
            BlockTree                    blockTree     = Build.A.BlockTree().OfChainLength(1).TestObject;
            MainnetSpecProvider          specProvider  = MainnetSpecProvider.Instance;
            ITransactionComparerProvider transactionComparerProvider =
                new TransactionComparerProvider(MainnetSpecProvider.Instance, blockTree);
            ITxPool txPool = new TxPool.TxPool(
                ecdsa,
                new ChainHeadInfoProvider(specProvider, blockTree, stateProvider),
                new TxPoolConfig(),
                new TxValidator(specProvider.ChainId),
                LimboLogs.Instance,
                transactionComparerProvider.GetDefaultComparer());
            IWallet          wallet           = new DevWallet(new WalletConfig(), LimboLogs.Instance);
            ReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(ecdsa, specProvider);
            LogFinder        logFinder        = new LogFinder(blockTree, new InMemoryReceiptStorage(), NullBloomStorage.Instance,
                                                              LimboLogs.Instance, receiptsRecovery, 1024);

            ReadOnlyTxProcessingEnv processingEnv = new ReadOnlyTxProcessingEnv(
                new ReadOnlyDbProvider(memDbProvider, false),
                new TrieStore(memDbProvider.StateDb, LimboLogs.Instance).AsReadOnly(memDbProvider.StateDb),
                new ReadOnlyBlockTree(blockTree),
                specProvider, LimboLogs.Instance);
            BlockchainBridge blockchainBridge = new BlockchainBridge(
                processingEnv,
                txPool,
                new InMemoryReceiptStorage(),
                NullFilterStore.Instance,
                NullFilterManager.Instance,
                ecdsa,
                Timestamper.Default,
                logFinder,
                specProvider,
                false);

            WalletTxSigner txSigner  = new WalletTxSigner(wallet, ChainId.Mainnet);
            ITxSealer      txSealer0 = new TxSealer(txSigner, Timestamper.Default);
            ITxSealer      txSealer1 = new NonceReservingTxSealer(txSigner, Timestamper.Default, txPool);
            ITxSender      txSender  = new TxPoolSender(txPool, txSealer0, txSealer1);

            return(new NdmBlockchainBridge(blockchainBridge, blockTree, stateReader, txSender));
        }
Example #8
0
        protected override async Task <TestBlockchain> Build(ISpecProvider specProvider = null, UInt256?initialValues = null)
        {
            BloomStorage bloomStorage = new BloomStorage(new BloomConfig(), new MemDb(), new InMemoryDictionaryFileStoreFactory());

            specProvider ??= MainnetSpecProvider.Instance;
            await base.Build(specProvider, initialValues);

            IFilterStore   filterStore   = new FilterStore();
            IFilterManager filterManager = new FilterManager(filterStore, BlockProcessor, TxPool, LimboLogs.Instance);

            ReceiptsRecovery receiptsRecovery = new ReceiptsRecovery(new EthereumEcdsa(specProvider.ChainId, LimboLogs.Instance), specProvider);

            LogFinder = new LogFinder(BlockTree, ReceiptStorage, bloomStorage, LimboLogs.Instance, receiptsRecovery);

            ReadOnlyTxProcessingEnv processingEnv = new ReadOnlyTxProcessingEnv(
                new ReadOnlyDbProvider(DbProvider, false),
                new TrieStore(DbProvider.StateDb, LimboLogs.Instance).AsReadOnly(),
                new ReadOnlyBlockTree(BlockTree),
                SpecProvider,
                LimboLogs.Instance);

            Bridge ??= new BlockchainBridge(processingEnv, TxPool, ReceiptStorage, filterStore, filterManager, EthereumEcdsa, Timestamper, LogFinder, SpecProvider, false, false);
            BlockFinder ??= BlockTree;

            ITxSigner txSigner  = new WalletTxSigner(TestWallet, specProvider?.ChainId ?? 0);
            ITxSealer txSealer0 = new TxSealer(txSigner, Timestamper);
            ITxSealer txSealer1 = new NonceReservingTxSealer(txSigner, Timestamper, TxPool);

            TxSender ??= new TxPoolSender(TxPool, txSealer0, txSealer1);

            EthRpcModule = new EthRpcModule(
                new JsonRpcConfig(),
                Bridge,
                BlockFinder,
                StateReader,
                TxPool,
                TxSender,
                TestWallet,
                LimboLogs.Instance,
                SpecProvider);

            return(this);
        }
Example #9
0
        public async Task <long> DownloadBlocks(PeerInfo bestPeer, int numberOfLatestBlocksToBeIgnored, CancellationToken cancellation, BlockDownloaderOptions options = BlockDownloaderOptions.Process)
        {
            IReceiptsRecovery receiptsRecovery = new ReceiptsRecovery();

            if (bestPeer == null)
            {
                string message = $"Not expecting best peer to be null inside the {nameof(BlockDownloader)}";
                if (_logger.IsError)
                {
                    _logger.Error(message);
                }
                throw new ArgumentNullException(message);
            }

            bool downloadReceipts = (options & BlockDownloaderOptions.DownloadReceipts) == BlockDownloaderOptions.DownloadReceipts;
            bool shouldProcess    = (options & BlockDownloaderOptions.Process) == BlockDownloaderOptions.Process;
            bool shouldMoveToMain = (options & BlockDownloaderOptions.MoveToMain) == BlockDownloaderOptions.MoveToMain;

            int blocksSynced        = 0;
            int ancestorLookupLevel = 0;


            long currentNumber = Math.Max(0, Math.Min(_blockTree.BestKnownNumber, bestPeer.HeadNumber - 1));

            // pivot number - 6 for uncle validation
            // long currentNumber = Math.Max(Math.Max(0, pivotNumber - 6), Math.Min(_blockTree.BestKnownNumber, bestPeer.HeadNumber - 1));

            while (bestPeer.TotalDifficulty > (_blockTree.BestSuggestedHeader?.TotalDifficulty ?? 0) && currentNumber <= bestPeer.HeadNumber)
            {
                if (_logger.IsDebug)
                {
                    _logger.Debug($"Continue full sync with {bestPeer} (our best {_blockTree.BestKnownNumber})");
                }

                long blocksLeft       = bestPeer.HeadNumber - currentNumber - numberOfLatestBlocksToBeIgnored;
                int  headersToRequest = (int)Math.Min(blocksLeft + 1, _syncBatchSize.Current);
                if (headersToRequest <= 1)
                {
                    break;
                }

                headersToRequest = Math.Min(headersToRequest, bestPeer.MaxHeadersPerRequest());
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Full sync request {currentNumber}+{headersToRequest} to peer {bestPeer} with {bestPeer.HeadNumber} blocks. Got {currentNumber} and asking for {headersToRequest} more.");
                }

                if (cancellation.IsCancellationRequested)
                {
                    return(blocksSynced);                                      // check before every heavy operation
                }
                BlockHeader[] headers = await RequestHeaders(bestPeer, cancellation, currentNumber, headersToRequest);

                BlockDownloadContext context = new BlockDownloadContext(_specProvider, bestPeer, headers, downloadReceipts, receiptsRecovery);

                if (cancellation.IsCancellationRequested)
                {
                    return(blocksSynced);                                      // check before every heavy operation
                }
                await RequestBodies(bestPeer, cancellation, context);

                if (downloadReceipts)
                {
                    if (cancellation.IsCancellationRequested)
                    {
                        return(blocksSynced);                                      // check before every heavy operation
                    }
                    await RequestReceipts(bestPeer, cancellation, context);
                }

                _sinceLastTimeout++;
                if (_sinceLastTimeout > 2)
                {
                    _syncBatchSize.Expand();
                }

                Block[] blocks    = context.Blocks;
                Block   blockZero = blocks[0];
                if (context.FullBlocksCount > 0)
                {
                    bool parentIsKnown = _blockTree.IsKnownBlock(blockZero.Number - 1, blockZero.ParentHash);
                    if (!parentIsKnown)
                    {
                        ancestorLookupLevel++;
                        if (ancestorLookupLevel >= _ancestorJumps.Length)
                        {
                            if (_logger.IsWarn)
                            {
                                _logger.Warn($"Could not find common ancestor with {bestPeer}");
                            }
                            throw new EthSynchronizationException("Peer with inconsistent chain in sync");
                        }

                        int ancestorJump = _ancestorJumps[ancestorLookupLevel] - _ancestorJumps[ancestorLookupLevel - 1];
                        currentNumber = currentNumber >= ancestorJump ? (currentNumber - ancestorJump) : 0L;
                        continue;
                    }
                }

                ancestorLookupLevel = 0;
                for (int blockIndex = 0; blockIndex < context.FullBlocksCount; blockIndex++)
                {
                    if (cancellation.IsCancellationRequested)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace("Peer sync cancelled");
                        }
                        break;
                    }

                    Block currentBlock = blocks[blockIndex];
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Received {currentBlock} from {bestPeer}");
                    }

                    // can move this to block tree now?
                    if (!_blockValidator.ValidateSuggestedBlock(currentBlock))
                    {
                        throw new EthSynchronizationException($"{bestPeer} sent an invalid block {currentBlock.ToString(Block.Format.Short)}.");
                    }

                    if (HandleAddResult(bestPeer, currentBlock.Header, blockIndex == 0, _blockTree.SuggestBlock(currentBlock, shouldProcess)))
                    {
                        if (downloadReceipts)
                        {
                            for (int receiptIndex = 0; receiptIndex < (context.ReceiptsForBlocks[blockIndex]?.Length ?? 0); receiptIndex++)
                            {
                                _receiptStorage.Add(context.ReceiptsForBlocks[blockIndex][receiptIndex], true);
                            }
                        }

                        blocksSynced++;
                    }

                    if (shouldMoveToMain)
                    {
                        _blockTree.UpdateMainChain(new[] { currentBlock }, false);
                    }

                    currentNumber += 1;
                }

                if (blocksSynced > 0)
                {
                    _syncReport.FullSyncBlocksDownloaded.Update(_blockTree.BestSuggestedHeader?.Number ?? 0);
                    _syncReport.FullSyncBlocksKnown = bestPeer.HeadNumber;
                }
                else
                {
                    break;
                }
            }

            return(blocksSynced);
        }
        private void Initialize(bool auRa = false)
        {
            ISpecProvider  specProvider  = MainnetSpecProvider.Instance;
            IEthereumEcdsa ethereumEcdsa = new EthereumEcdsa(specProvider, LimboLogs.Instance);
            ITxStorage     txStorage     = new InMemoryTxStorage();

            _stateDb = new StateDb();
            ISnapshotableDb codeDb      = new StateDb();
            IStateReader    stateReader = new StateReader(_stateDb, codeDb, LimboLogs.Instance);

            _stateProvider = new StateProvider(_stateDb, codeDb, LimboLogs.Instance);
            _stateProvider.CreateAccount(TestItem.AddressA, 1000.Ether());
            _stateProvider.CreateAccount(TestItem.AddressB, 1000.Ether());
            _stateProvider.CreateAccount(TestItem.AddressC, 1000.Ether());
            byte[] code     = Bytes.FromHexString("0xabcd");
            Keccak codeHash = Keccak.Compute(code);

            _stateProvider.UpdateCode(code);
            _stateProvider.UpdateCodeHash(TestItem.AddressA, codeHash, specProvider.GenesisSpec);

            IStorageProvider storageProvider = new StorageProvider(_stateDb, _stateProvider, LimboLogs.Instance);

            storageProvider.Set(new StorageCell(TestItem.AddressA, UInt256.One), Bytes.FromHexString("0xabcdef"));
            storageProvider.Commit();

            _stateProvider.Commit(specProvider.GenesisSpec);
            _stateProvider.CommitTree();

            ITxPool txPool = new TxPool.TxPool(txStorage, Timestamper.Default, ethereumEcdsa, specProvider, new TxPoolConfig(), _stateProvider, LimboLogs.Instance);

            IDb        blockDb     = new MemDb();
            IDb        headerDb    = new MemDb();
            IDb        blockInfoDb = new MemDb();
            IBlockTree blockTree   = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockDb), specProvider, txPool, NullBloomStorage.Instance, LimboLogs.Instance);

            IReceiptStorage      receiptStorage = new InMemoryReceiptStorage();
            VirtualMachine       virtualMachine = new VirtualMachine(_stateProvider, storageProvider, new BlockhashProvider(blockTree, LimboLogs.Instance), specProvider, LimboLogs.Instance);
            TransactionProcessor txProcessor    = new TransactionProcessor(specProvider, _stateProvider, storageProvider, virtualMachine, LimboLogs.Instance);
            IBlockProcessor      blockProcessor = new BlockProcessor(specProvider, Always.Valid, new RewardCalculator(specProvider), txProcessor, _stateDb, codeDb, _stateProvider, storageProvider, txPool, receiptStorage, LimboLogs.Instance);

            IFilterStore   filterStore   = new FilterStore();
            IFilterManager filterManager = new FilterManager(filterStore, blockProcessor, txPool, LimboLogs.Instance);

            _blockchainBridge = new BlockchainBridge(stateReader, _stateProvider, storageProvider, blockTree, txPool, receiptStorage, filterStore, filterManager, NullWallet.Instance, txProcessor, ethereumEcdsa, NullBloomStorage.Instance, LimboLogs.Instance, false);

            BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ethereumEcdsa, txPool, LimboLogs.Instance), LimboLogs.Instance, true);

            blockchainProcessor.Start();

            ManualResetEventSlim resetEvent = new ManualResetEventSlim(false);

            blockTree.NewHeadBlock += (s, e) =>
            {
                Console.WriteLine(e.Block.Header.Hash);
                if (e.Block.Number == 9)
                {
                    resetEvent.Set();
                }
            };

            var genesisBlockBuilder = Build.A.Block.Genesis.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"));

            if (auRa)
            {
                genesisBlockBuilder.WithAura(0, new byte[65]);
            }

            Block genesis = genesisBlockBuilder.TestObject;

            blockTree.SuggestBlock(genesis);

            Block previousBlock = genesis;

            for (int i = 1; i < 10; i++)
            {
                List <Transaction> transactions = new List <Transaction>();
                for (int j = 0; j < i; j++)
                {
                    transactions.Add(Build.A.Transaction.WithNonce((UInt256)j).SignedAndResolved().TestObject);
                }

                BlockBuilder builder = Build.A.Block.WithNumber(i).WithParent(previousBlock).WithTransactions(transactions.ToArray()).WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"));
                if (auRa)
                {
                    builder.WithAura(i, i.ToByteArray());
                }

                Block block = builder.TestObject;
                blockTree.SuggestBlock(block);
                previousBlock = block;
            }

            IReceiptsRecovery receiptsRecovery = new ReceiptsRecovery();
            IReceiptFinder    receiptFinder    = new FullInfoReceiptFinder(receiptStorage, receiptsRecovery, blockTree);

            resetEvent.Wait(2000);
            _traceModule = new TraceModule(receiptFinder, new Tracer(_stateProvider, blockchainProcessor), _blockchainBridge);
            _blockTree   = blockTree;
        }