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); }
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); }
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); } }
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); } }
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); } }
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); }
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); } }
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); } }
=> _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); }
// TODO: block processor pipeline private void StoreTxReceipts(Block block, TxReceipt[] txReceipts) { _receiptStorage.Insert(block, txReceipts); }
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); }
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; } } } }
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);
public void Insert(Block block, params TxReceipt[] txReceipts) { _outStorage.Insert(block, txReceipts); }
// 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); }