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);
        }
Exemple #2
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
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);
        }