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, blockIndex + 1).TestObject, Build.A.Transaction.WithValue(2).WithData(Rlp.Encode(blockIndex + 1).Bytes).Signed(_ecdsa, TestItem.PrivateKeyA, blockIndex + 1).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; currentBlock.Header.ReceiptsRoot = new ReceiptTrie(currentBlock.Number, _specProvider, receipts.ToArray()).RootHash; currentBlock.Header.Hash = currentBlock.CalculateHash(); foreach (TxReceipt receipt in receipts) { receipt.BlockHash = currentBlock.Hash; receipt.BlockNumber = currentBlock.Number; _receiptStorage.Add(receipt, false); } } 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 Block CreateBlock(int splitVariant, int splitFrom, int i, Block parent) { Block current; if (_receiptStorage != null && i % 3 == 0) { Transaction[] transactions = new[] { Build.A.Transaction.WithData(Rlp.Encode(i).Bytes).Signed(_ecdsa, TestItem.PrivateKeyA, i + 1).TestObject }; current = Build.A.Block .WithNumber(i + 1) .WithParent(parent) .WithDifficulty(BlockHeaderBuilder.DefaultDifficulty - (splitFrom > parent.Number ? 0 : (ulong)splitVariant)) .WithTransactions(transactions) .TestObject; List <TxReceipt> receipts = new List <TxReceipt>(); foreach (Transaction transaction in current.Transactions) { TxReceipt receipt = new TxReceipt(); receipt.TxHash = transaction.Hash; _receiptStorage.Add(receipt, false); receipts.Add(receipt); } current.Header.TxRoot = current.CalculateTxRoot(); current.Header.ReceiptsRoot = current.CalculateReceiptRoot(_specProvider, receipts.ToArray()); current.Hash = BlockHeader.CalculateHash(current); } else { current = Build.A.Block.WithNumber(i + 1).WithParent(parent).WithDifficulty(BlockHeaderBuilder.DefaultDifficulty - (splitFrom > parent.Number ? 0 : (ulong)splitVariant)).TestObject; } return(current); }
private void StoreTxReceipts(Block block, TxReceipt[] txReceipts) { for (int i = 0; i < block.Transactions.Length; i++) { txReceipts[i].BlockHash = block.Hash; _receiptStorage.Add(txReceipts[i], true); _txPool.RemoveTransaction(txReceipts[i].TxHash, block.Number); } }
private void StoreTxReceipts(Block block, TransactionReceipt[] transactionReceipts) { for (int i = 0; i < block.Transactions.Length; i++) { transactionReceipts[i].BlockHash = block.Hash; _receiptStorage.Add(transactionReceipts[i]); _txPool.RemoveTransaction(transactionReceipts[i].TransactionHash); } }
private void TestAddAndGetReceipt(IReceiptStorage storage) { var transaction = GetSignedTransaction(); var receipt = GetReceipt(transaction); storage.Add(receipt); var fetchedReceipt = storage.Get(transaction.Hash); receipt.PostTransactionState.Should().Be(fetchedReceipt.PostTransactionState); }
private void TestAddAndGetReceiptEip658(IReceiptStorage storage) { var transaction = GetSignedTransaction(); var receipt = GetReceipt(transaction); storage.Add(receipt, true); var fetchedReceipt = storage.Find(transaction.Hash); receipt.StatusCode.Should().Be(fetchedReceipt.StatusCode); receipt.PostTransactionState.Should().Be(fetchedReceipt.PostTransactionState); }
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); }