public TxReceipt[] Get(Block block)
        {
            var receipts = _receiptStorage.Get(block);

            if (_receiptsRecovery.TryRecover(block, receipts) == ReceiptsRecoveryResult.Success)
            {
                _receiptStorage.Insert(block, receipts);
            }

            return(receipts);
        }
            private async Task <bool> DownloadReceiptsForBlock(Block block)
            {
                if (block.Hash == null)
                {
                    throw new ArgumentException("Cannot download receipts for a block without a known hash.");
                }

                FastBlocksAllocationStrategy strategy = new FastBlocksAllocationStrategy(TransferSpeedType.Receipts, block.Number, true);
                SyncPeerAllocation           peer     = await _syncPeerPool.Allocate(strategy, AllocationContexts.Receipts);

                ISyncPeer?currentSyncPeer = peer.Current?.SyncPeer;

                if (currentSyncPeer != null)
                {
                    try
                    {
                        TxReceipt[][]? receipts = await currentSyncPeer.GetReceipts(new List <Keccak> {
                            block.Hash
                        }, _cancellationToken);

                        TxReceipt[]? txReceipts = receipts?.FirstOrDefault();
                        if (txReceipts != null)
                        {
                            _receiptStorage.Insert(block, txReceipts);
                            if (_logger.IsInfo)
                            {
                                _logger.Info($"Downloaded missing receipts for block {block.ToString(Block.Format.FullHashAndNumber)}.");
                            }
                            return(true);
                        }
                        else
                        {
                            if (_logger.IsInfo)
                            {
                                _logger.Error($"Fail to download missing receipts for block {block.ToString(Block.Format.FullHashAndNumber)}.");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        if (_logger.IsInfo)
                        {
                            _logger.Error($"Fail to download missing receipts for block {block.ToString(Block.Format.FullHashAndNumber)}.", e);
                        }
                    }
                    finally
                    {
                        _syncPeerPool.Free(peer);
                    }
                }
                else
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Error($"Fail to download missing receipts for block {block.ToString(Block.Format.FullHashAndNumber)}. No peer available.");
                    }
                }

                return(false);
            }
Exemplo n.º 3
0
        private Block CreateBlock(int splitVariant, int splitFrom, int blockIndex, Block parent, Address beneficiary)
        {
            Block currentBlock;

            if (_receiptStorage != null && blockIndex % 3 == 0)
            {
                Transaction[] transactions = new[]
                {
                    Build.A.Transaction.WithValue(1).WithData(Rlp.Encode(blockIndex).Bytes).Signed(_ecdsa, TestItem.PrivateKeyA, _specProvider.GetSpec(blockIndex + 1).IsEip155Enabled).TestObject,
                    Build.A.Transaction.WithValue(2).WithData(Rlp.Encode(blockIndex + 1).Bytes).Signed(_ecdsa, TestItem.PrivateKeyA, _specProvider.GetSpec(blockIndex + 1).IsEip155Enabled).TestObject
                };

                currentBlock = Build.A.Block
                               .WithNumber(blockIndex + 1)
                               .WithParent(parent)
                               .WithDifficulty(BlockHeaderBuilder.DefaultDifficulty - (splitFrom > parent.Number ? 0 : (ulong)splitVariant))
                               .WithTransactions(transactions)
                               .WithBloom(new Bloom())
                               .WithBeneficiary(beneficiary)
                               .TestObject;

                List <TxReceipt> receipts = new List <TxReceipt>();
                foreach (var transaction in currentBlock.Transactions)
                {
                    var       logEntries = _logCreationFunction?.Invoke(currentBlock, transaction)?.ToArray() ?? Array.Empty <LogEntry>();
                    TxReceipt receipt    = new TxReceipt
                    {
                        Logs   = logEntries,
                        TxHash = transaction.Hash,
                        Bloom  = new Bloom(logEntries)
                    };

                    receipts.Add(receipt);
                    currentBlock.Bloom.Add(receipt.Logs);
                }

                currentBlock.Header.TxRoot = new TxTrie(currentBlock.Transactions).RootHash;
                var txReceipts = receipts.ToArray();
                currentBlock.Header.ReceiptsRoot = new ReceiptTrie(currentBlock.Number, _specProvider, txReceipts).RootHash;
                currentBlock.Header.Hash         = currentBlock.CalculateHash();
                foreach (var txReceipt in txReceipts)
                {
                    txReceipt.BlockHash = currentBlock.Hash;
                }

                _receiptStorage.Insert(currentBlock, false, txReceipts);
            }
            else
            {
                currentBlock = Build.A.Block.WithNumber(blockIndex + 1)
                               .WithParent(parent)
                               .WithDifficulty(BlockHeaderBuilder.DefaultDifficulty - (splitFrom > parent.Number ? 0 : (ulong)splitVariant))
                               .WithBeneficiary(beneficiary)
                               .TestObject;
            }

            currentBlock.Header.AuRaStep = blockIndex;

            return(currentBlock);
        }
Exemplo n.º 4
0
        private void TestAddAndGetReceipt(IReceiptStorage storage, IReceiptFinder receiptFinder = null)
        {
            bool recoverSender = receiptFinder is not null;

            receiptFinder ??= storage;

            var transaction = GetSignedTransaction();

            transaction.SenderAddress = null;
            var block   = GetBlock(transaction);
            var receipt = GetReceipt(transaction, block);

            storage.Insert(block, receipt);
            var blockHash = storage.FindBlockHash(transaction.Hash);

            blockHash.Should().Be(block.Hash);
            var fetchedReceipt = receiptFinder.Get(block).ForTransaction(transaction.Hash);

            receipt.StatusCode.Should().Be(fetchedReceipt.StatusCode);
            receipt.PostTransactionState.Should().Be(fetchedReceipt.PostTransactionState);
            receipt.TxHash.Should().Be(transaction.Hash);
            if (recoverSender)
            {
                receipt.Sender.Should().BeEquivalentTo(TestItem.AddressA);
            }
        }
Exemplo n.º 5
0
 private void StoreTxReceipts(Block block, TxReceipt[] txReceipts)
 {
     _receiptStorage.Insert(block, false, txReceipts);
     for (int i = 0; i < block.Transactions.Length; i++)
     {
         _txPool.RemoveTransaction(txReceipts[i].TxHash, block.Number);
     }
 }
Exemplo n.º 6
0
        private void TestAddAndCheckLowest(IReceiptStorage storage, bool updateLowest)
        {
            var transaction = GetSignedTransaction();
            var block       = GetBlock(transaction);
            var receipt     = GetReceipt(transaction, block);

            storage.Insert(block, updateLowest, receipt);
            storage.LowestInsertedReceiptBlock.Should().Be(updateLowest ? (long?)0 : null);
        }
 private void RollbackReceipts(Block?previousBlock)
 {
     if (previousBlock != null)
     {
         TxReceipt[] txReceipts = _receiptStorage.Get(previousBlock);
         foreach (var txReceipt in txReceipts)
         {
             txReceipt.Removed = true;
         }
         _receiptStorage.Insert(previousBlock, txReceipts);
     }
 }
Exemplo n.º 8
0
        private void TestAddAndCheckLowest(IReceiptStorage storage, bool updateLowest)
        {
            Transaction transaction = GetSignedTransaction();
            Block       block       = GetBlock(transaction);
            TxReceipt   receipt     = GetReceipt(transaction, block);

            storage.Insert(block, receipt);
            if (updateLowest)
            {
                storage.LowestInsertedReceiptBlockNumber = block.Number;
            }

            storage.LowestInsertedReceiptBlockNumber.Should().Be(updateLowest ? 0 : null);
        }
        private void TestAddAndGetReceiptEip658(IReceiptStorage storage)
        {
            var transaction = GetSignedTransaction();
            var block       = GetBlock(transaction);
            var receipt     = GetReceipt(transaction, block);

            storage.Insert(block, receipt);
            var blockHash = storage.FindBlockHash(transaction.Hash);

            blockHash.Should().Be(block.Hash);
            var fetchedReceipt = storage.Get(block).ForTransaction(transaction.Hash);

            receipt.StatusCode.Should().Be(fetchedReceipt.StatusCode);
            receipt.PostTransactionState.Should().Be(fetchedReceipt.PostTransactionState);
            receipt.TxHash.Should().Be(transaction.Hash);
        }
Exemplo n.º 10
0
        public void CreateOrUpdate(ReceiptBindingModel model)
        {
            var element = _receiptStorage.GetElement(new ReceiptBindingModel {
                PurchaseDate = model.PurchaseDate
            });

            if (element != null && element.Id != model.Id)
            {
                throw new Exception("Уже пробит чек в данное время");
            }
            if (model.Id.HasValue)
            {
                _receiptStorage.Update(model);
            }
            else
            {
                _receiptStorage.Insert(model);
            }
        }
Exemplo n.º 11
0
        public void CreateOrUpdate(ReceiptBindingModel model)
        {
            var element = _receiptStorage.GetElement(new ReceiptBindingModel {
                Id = model.Id
            });

            if (element != null && element.Id != model.Id)
            {
                throw new Exception("Уже есть выписка с таким названием");
            }
            if (model.Id.HasValue)
            {
                _receiptStorage.Update(model);
            }
            else
            {
                _receiptStorage.Insert(model);
            }
        }
Exemplo n.º 12
0
        => _receiptsMigration.Run(blockNumber + 1);     // add 1 to make go from inclusive (better for API) to exclusive (better for internal)

        public void InsertReceipts(BlockParameter blockParameter, TxReceipt[] txReceipts)
        {
            SearchResult <Block> searchResult = _blockTree.SearchForBlock(blockParameter);

            if (searchResult.IsError)
            {
                throw new InvalidDataException(searchResult.Error);
            }

            Block       block       = searchResult.Object;
            ReceiptTrie receiptTrie = new ReceiptTrie(block.Number, _specProvider, txReceipts);

            receiptTrie.UpdateRootHash();
            if (block.ReceiptsRoot != receiptTrie.RootHash)
            {
                throw new InvalidDataException("Receipts root mismatch");
            }

            _receiptStorage.Insert(block, txReceipts);
        }
Exemplo n.º 13
0
 // TODO: block processor pipeline
 private void StoreTxReceipts(Block block, TxReceipt[] txReceipts)
 {
     _receiptStorage.Insert(block, txReceipts);
 }
Exemplo n.º 14
0
        public async Task <long> DownloadBlocks(PeerInfo bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation)
        {
            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);
            }

            DownloaderOptions options = blocksRequest.Options;
            bool downloadReceipts     = (options & DownloaderOptions.WithReceipts) == DownloaderOptions.WithReceipts;
            bool shouldProcess        = (options & DownloaderOptions.Process) == DownloaderOptions.Process;
            bool shouldMoveToMain     = (options & DownloaderOptions.MoveToMain) == DownloaderOptions.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 - (blocksRequest.NumberOfLatestBlocksToBeIgnored ?? 0);
                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 EthSyncException("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 EthSyncException($"{bestPeer} sent an invalid block {currentBlock.ToString(Block.Format.Short)}.");
                    }

                    if (HandleAddResult(bestPeer, currentBlock.Header, blockIndex == 0, _blockTree.SuggestBlock(currentBlock, shouldProcess)))
                    {
                        if (downloadReceipts)
                        {
                            var contextReceiptsForBlock = context.ReceiptsForBlocks[blockIndex];
                            if (contextReceiptsForBlock != null)
                            {
                                _receiptStorage.Insert(currentBlock, false, contextReceiptsForBlock);
                            }
                        }

                        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);
        }
Exemplo n.º 15
0
        private IEnumerable <FilterLog> FilterLogsInBlockHighMemoryAllocation(LogFilter filter, Keccak blockHash, long blockNumber, CancellationToken cancellationToken)
        {
            TxReceipt[]? GetReceipts(Keccak hash, long number)
            {
                var canUseHash = _receiptFinder.CanGetReceiptsByHash(number);

                if (canUseHash)
                {
                    return(_receiptFinder.Get(hash));
                }
                else
                {
                    var block = _blockFinder.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                    return(block == null ? null : _receiptFinder.Get(block));
                }
            }

            void RecoverReceiptsData(Keccak hash, TxReceipt[] receipts)
            {
                if (_receiptsRecovery.NeedRecover(receipts))
                {
                    var block = _blockFinder.FindBlock(hash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                    if (block != null)
                    {
                        if (_receiptsRecovery.TryRecover(block, receipts) == ReceiptsRecoveryResult.Success)
                        {
                            _receiptStorage.Insert(block, receipts);
                        }
                    }
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            var  receipts        = GetReceipts(blockHash, blockNumber);
            long logIndexInBlock = 0;

            if (receipts != null)
            {
                for (var i = 0; i < receipts.Length; i++)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var receipt = receipts[i];

                    if (filter.Matches(receipt.Bloom))
                    {
                        for (var j = 0; j < receipt.Logs.Length; j++)
                        {
                            cancellationToken.ThrowIfCancellationRequested();

                            var log = receipt.Logs[j];
                            if (filter.Accepts(log))
                            {
                                RecoverReceiptsData(blockHash, receipts);
                                yield return(new FilterLog(logIndexInBlock, j, receipt, log));
                            }

                            logIndexInBlock++;
                        }
                    }
                    else
                    {
                        logIndexInBlock += receipt.Logs.Length;
                    }
                }
            }
        }
Exemplo n.º 16
0
 public void Insert(Block block, bool updateLowestInserted, params TxReceipt[] txReceipts)
 {
     _outStorage.Insert(block, updateLowestInserted, txReceipts);
 }
 public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical) => _outStorage.Insert(block, txReceipts);
Exemplo n.º 18
0
 public void Insert(Block block, params TxReceipt[] txReceipts)
 {
     _outStorage.Insert(block, txReceipts);
 }
Exemplo n.º 19
0
 // TODO: block processor pipeline
 private void StoreTxReceipts(Block block, TxReceipt[] txReceipts)
 {
     // Setting canonical is done by ReceiptCanonicalityMonitor on block move to main
     _receiptStorage.Insert(block, txReceipts, false);
 }