Exemplo n.º 1
0
        private IEnumerable <FilterLog> FilterLogsWithBloomsIndex(LogFilter filter, BlockHeader fromBlock, BlockHeader toBlock)
        {
            Block FindBlock(long blockNumber)
            {
                var block = _blockFinder.FindBlock(blockNumber);

                if (block == null)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error($"Could not find block {blockNumber} in database. eth_getLogs will return incomplete results.");
                    }
                }
                return(block);
            }

            var enumeration = _bloomStorage.GetBlooms(fromBlock.Number, toBlock.Number);

            foreach (var bloom in enumeration)
            {
                if (filter.Matches(bloom) && enumeration.TryGetBlockNumber(out var blockNumber))
                {
                    foreach (var filterLog in FindLogsInBlock(filter, FindBlock(blockNumber)))
                    {
                        yield return(filterLog);
                    }
                }
            }
        }
Exemplo n.º 2
0
        public static SearchResult <Block> SearchForBlock(this IBlockFinder blockFinder, BlockParameter blockParameter, bool allowNulls = false)
        {
            Block block;

            if (blockParameter.RequireCanonical)
            {
                block = blockFinder.FindBlock(blockParameter.BlockHash, BlockTreeLookupOptions.RequireCanonical);
                if (block == null && !allowNulls)
                {
                    var header = blockFinder.FindHeader(blockParameter.BlockHash);
                    if (header != null)
                    {
                        return(new SearchResult <Block>($"{blockParameter.BlockHash} block is not canonical", ErrorCodes.InvalidInput));
                    }
                }
            }
            else
            {
                block = blockFinder.FindBlock(blockParameter);
            }

            return(block == null && !allowNulls
                ? new SearchResult <Block>($"{blockParameter.BlockHash?.ToString() ?? blockParameter.BlockNumber?.ToString() ?? blockParameter.Type.ToString()} could not be found", ErrorCodes.ResourceNotFound)
                : new SearchResult <Block>(block));
        }
Exemplo n.º 3
0
        private IEnumerable <FilterLog> FilterLogsInBlockHighMemoryAllocation(LogFilter filter, Keccak blockHash, long blockNumber)
        {
            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)
                    {
                        _receiptsRecovery.TryRecover(block, receipts);
                    }
                }
            }

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

            if (receipts != null)
            {
                for (var i = 0; i < receipts.Length; i++)
                {
                    var receipt = receipts[i];

                    if (filter.Matches(receipt.Bloom))
                    {
                        for (var j = 0; j < receipt.Logs.Length; j++)
                        {
                            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.º 4
0
        public async Task find_block_by_hash_should_invoke_blockchain_bridge_find_block_by_hash()
        {
            var block = Build.A.Block.TestObject;

            _blockFinder.FindBlock(block.Hash).Returns(block);
            var result = await _ndmBridge.FindBlockAsync(block.Hash);

            _blockFinder.Received().FindBlock(block.Hash);
            result.Should().Be(block);
        }
Exemplo n.º 5
0
        private IEnumerable <FilterLog> FilterLogsWithBloomsIndex(LogFilter filter, BlockHeader fromBlock, BlockHeader toBlock)
        {
            var enumeration = _bloomStorage.GetBlooms(fromBlock.Number, toBlock.Number);

            foreach (var bloom in enumeration)
            {
                if (filter.Matches(bloom) && enumeration.TryGetBlockNumber(out var blockNumber))
                {
                    foreach (var filterLog in FindLogsInBlock(filter, _blockFinder.FindBlock(blockNumber)))
                    {
                        yield return(filterLog);
                    }
                }
            }
        }
Exemplo n.º 6
0
        public ResultWrapper <ReceiptForRpc[]> parity_getBlockReceipts(BlockParameter blockParameter)
        {
            Block block = _blockFinder.FindBlock(blockParameter);

            TxReceipt[] receipts = _receiptStorage.FindForBlock(block, new ReceiptsRecovery());
            IEnumerable <ReceiptForRpc> result = receipts.Zip(block.Transactions, (r, t) => new ReceiptForRpc(t.Hash, r));

            return(ResultWrapper <ReceiptForRpc[]> .Success(result.ToArray()));
        }
Exemplo n.º 7
0
        public static Block?FindParent(this IBlockFinder finder, BlockHeader blockHeader, BlockTreeLookupOptions options)
        {
            if (blockHeader.ParentHash is null)
            {
                throw new InvalidOperationException(
                          $"Cannot find parent when parent hash is null on block with hash {blockHeader.Hash}.");
            }

            return(finder.FindBlock(blockHeader.ParentHash, options));
        }
Exemplo n.º 8
0
        private IBlockFinder GetBlockFinderForLastFiveBlocksWithThreeTxAndFirstFourWithOne()
        {
            IBlockFinder blockFinder      = Substitute.For <IBlockFinder>();
            Transaction  tx               = Build.A.Transaction.TestObject;
            Block        blockWithOneTx   = Build.A.Block.WithTransactions(Enumerable.Repeat(tx, 1).ToArray()).TestObject;
            Block        blockWithThreeTx = Build.A.Block.WithTransactions(Enumerable.Repeat(tx, 3).ToArray()).TestObject;

            for (int i = 0; i < 4; i++)
            {
                blockFinder.FindBlock(i).Returns(blockWithOneTx);
            }
            for (int i = 4; i <= 8; i++)
            {
                blockFinder.FindBlock(i).Returns(blockWithThreeTx);
            }

            blockFinder.Head.Returns(Build.A.Block.WithNumber(8).TestObject);

            return(blockFinder);
        }
Exemplo n.º 9
0
        public TxReceipt[] Get(Keccak blockHash)
        {
            var receipts = _innerFinder.Get(blockHash);

            if (_receiptsRecovery.NeedRecover(receipts))
            {
                var block = _blockFinder.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                _receiptsRecovery.TryRecover(block, receipts);
            }

            return(receipts);
        }
        public void GetFeeHistory_IfRewardPercentilesContainInvalidNumber_ResultsInFailure(double[] rewardPercentiles)
        {
            int          blockCount  = 10;
            IBlockFinder blockFinder = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(BlockParameter.Latest).Returns(Build.A.Block.TestObject);
            FeeHistoryOracle feeHistoryOracle = GetSubstitutedFeeHistoryOracle(blockFinder: blockFinder);

            ResultWrapper <FeeHistoryResults> resultWrapper = feeHistoryOracle.GetFeeHistory(blockCount, BlockParameter.Latest, rewardPercentiles);

            resultWrapper.Result.Error.Should().Be("rewardPercentiles: Some values are below 0 or greater than 100.");
            resultWrapper.Result.ResultType.Should().Be(ResultType.Failure);
        }
Exemplo n.º 11
0
        public void GetGasPricesFromRecentBlocks_IfBlockHasMoreThanThreeValidTxs_OnlyAddTxsWithLowestGasPrices()
        {
            Block        testBlock   = Build.A.Block.WithTransactions(GetFiveTransactionsWithDifferentGasPrices()).TestObject;
            IBlockFinder blockFinder = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(0).Returns(testBlock);
            GasPriceOracle testGasPriceOracle = new(blockFinder, Substitute.For <ISpecProvider>());
            List <UInt256> expected           = new() { 2, 3, 4 };

            IEnumerable <UInt256> results = testGasPriceOracle.GetSortedGasPricesFromRecentBlocks(0);

            results.Should().BeEquivalentTo(expected);
        }
Exemplo n.º 12
0
 private bool TryGetParentBlock(Block currentBlock, out Block parentBlock)
 {
     if (currentBlock.IsGenesis)
     {
         parentBlock = null;
         return(false);
     }
     else
     {
         parentBlock = _blockFinder.FindBlock(currentBlock.ParentHash);
         return(true);
     }
 }
Exemplo n.º 13
0
        public void GetGasPricesFromRecentBlocks_IfBlockHasMoreThanThreeValidTx_AddOnlyThreeNew()
        {
            IBlockFinder blockFinder = Substitute.For <IBlockFinder>();
            Transaction  tx          = Build.A.Transaction.WithGasPrice(2).TestObject;
            Block        headBlock   = Build.A.Block.Genesis.WithTransactions(tx, tx, tx, tx, tx).TestObject;

            blockFinder.FindHeadBlock().Returns(headBlock);
            blockFinder.FindBlock(0).Returns(headBlock);
            GasPriceOracle testGasPriceOracle = new(blockFinder, Substitute.For <ISpecProvider>());

            IEnumerable <UInt256> results = testGasPriceOracle.GetSortedGasPricesFromRecentBlocks(0);

            results.Count().Should().Be(3);
        }
        public void GetFeeHistory_NewestBlockIsNull_ReturnsFailingWrapper()
        {
            IBlockFinder blockFinder = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(Arg.Any <long>()).Returns((Block?)null);
            FeeHistoryOracle feeHistoryOracle          = GetSubstitutedFeeHistoryOracle(blockFinder: blockFinder);
            ResultWrapper <FeeHistoryResults> expected =
                ResultWrapper <FeeHistoryResults> .Fail("newestBlock: Block is not available",
                                                        ErrorCodes.ResourceUnavailable);

            ResultWrapper <FeeHistoryResults> resultWrapper = feeHistoryOracle.GetFeeHistory(1, new BlockParameter((long)0));

            resultWrapper.Should().BeEquivalentTo(expected);
        }
Exemplo n.º 15
0
        private IBlockFinder BuildTree(int maxBlock)
        {
            IBlockFinder blockFinder    = Substitute.For <IBlockFinder>();
            Transaction  tx             = Build.A.Transaction.TestObject;
            Block        blockWithTwoTx = Build.A.Block.WithTransactions(tx, tx).TestObject;

            for (int i = 0; i <= maxBlock; i++)
            {
                blockFinder.FindBlock(i).Returns(blockWithTwoTx);
            }

            blockFinder.Head.Returns(Build.A.Block.WithNumber(maxBlock).TestObject);

            return(blockFinder);
        }
        public TxReceipt[] Get(Keccak blockHash)
        {
            var receipts = _receiptStorage.Get(blockHash);

            if (_receiptsRecovery.NeedRecover(receipts))
            {
                var block = _blockFinder.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                if (_receiptsRecovery.TryRecover(block, receipts) == ReceiptsRecoveryResult.Success)
                {
                    _receiptStorage.Insert(block, receipts);
                }
            }

            return(receipts);
        }
        public void GetFeeHistory_IfRewardPercentilesNotInAscendingOrder_ResultsInFailure()
        {
            int blockCount = 10;

            double[]     rewardPercentiles = { 0, 2, 3, 5, 1 };
            IBlockFinder blockFinder       = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(BlockParameter.Latest).Returns(Build.A.Block.TestObject);
            FeeHistoryOracle feeHistoryOracle = GetSubstitutedFeeHistoryOracle(blockFinder: blockFinder);

            ResultWrapper <FeeHistoryResults> resultWrapper = feeHistoryOracle.GetFeeHistory(blockCount, BlockParameter.Latest, rewardPercentiles);

            resultWrapper.Result.Error.Should().Be("rewardPercentiles: Value at index 4: 1 is less than or equal to the value at previous index 3: 5.");
            resultWrapper.Result.ResultType.Should().Be(ResultType.Failure);
        }
Exemplo n.º 18
0
        public void GasPriceEstimate_IfCalculatedGasPriceGreaterThanMax_MaxGasPriceReturned()
        {
            Transaction  tx          = Build.A.Transaction.WithGasPrice(501.GWei()).TestObject;
            Block        headBlock   = Build.A.Block.WithTransactions(tx).TestObject;
            IBlockFinder blockFinder = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(0).Returns(headBlock);
            blockFinder.Head.Returns(headBlock);
            ISpecProvider  specProvider       = Substitute.For <ISpecProvider>();
            GasPriceOracle testGasPriceOracle = new(blockFinder, specProvider);

            UInt256 result = testGasPriceOracle.GetGasPriceEstimate();

            result.Should().Be(500.GWei());
        }
Exemplo n.º 19
0
        public void GasPriceEstimate_EmptyChain_BaseFeeIncluded(ulong?gasPrice)
        {
            UInt256      baseFeePerGas = 10.GWei();
            Block        headBlock     = Build.A.Block.WithBaseFeePerGas(baseFeePerGas).TestObject;
            IBlockFinder blockFinder   = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(0).Returns(headBlock);
            blockFinder.Head.Returns(headBlock);
            ISpecProvider  specProvider       = Substitute.For <ISpecProvider>();
            GasPriceOracle testGasPriceOracle = new(blockFinder, specProvider, gasPrice);

            UInt256 estimate = testGasPriceOracle.GetGasPriceEstimate();

            estimate.Should().Be((baseFeePerGas + (gasPrice ?? 1.GWei())) * 110 / 100);
        }
        [TestCase(100, 40, 50, 49)] //Target gas used: 100/2 = 50 | Actual Gas used = 40 | Base Fee Delta = (((50-40)/50) * 50) / 8 = 1 | Next Base Fee = 50 - 1 = 49
        public void GetFeeHistory_IfLondonEnabled_NextBaseFeePerGasCalculatedCorrectly(long gasLimit, long gasUsed, long baseFee, long expectedNextBaseFee)
        {
            int            blockCount  = 1;
            IBlockFinder   blockFinder = Substitute.For <IBlockFinder>();
            BlockHeader    blockHeader = Build.A.BlockHeader.WithBaseFee((UInt256)baseFee).WithGasLimit(gasLimit).WithGasUsed(gasUsed).TestObject;
            BlockParameter newestBlock = new((long)0);
            Block          headBlock   = Build.A.Block.Genesis.WithHeader(blockHeader).TestObject;

            blockFinder.FindBlock(newestBlock).Returns(headBlock);
            ISpecProvider specProvider = GetSpecProviderWithEip1559EnabledAs(true);

            FeeHistoryOracle feeHistoryOracle = GetSubstitutedFeeHistoryOracle(blockFinder: blockFinder, specProvider: specProvider);

            ResultWrapper <FeeHistoryResults> resultWrapper = feeHistoryOracle.GetFeeHistory(blockCount, newestBlock);

            resultWrapper.Data.BaseFeePerGas ![1].Should().Be((UInt256)expectedNextBaseFee);
Exemplo n.º 21
0
        public ResultWrapper <FeeHistoryResults> GetFeeHistory(long blockCount, BlockParameter newestBlock, double[]?rewardPercentiles = null)
        {
            ResultWrapper <FeeHistoryResults> initialCheckResult = Validate(ref blockCount, newestBlock, rewardPercentiles);

            if (initialCheckResult.Result.ResultType == ResultType.Failure)
            {
                return(initialCheckResult);
            }

            Block?block = _blockFinder.FindBlock(newestBlock);

            if (block is null)
            {
                return(ResultWrapper <FeeHistoryResults> .Fail("newestBlock: Block is not available", ErrorCodes.ResourceUnavailable));
            }

            long            oldestBlockNumber = block !.Number;
            Stack <UInt256> baseFeePerGas     = new((int)(blockCount + 1));

            baseFeePerGas.Push(BaseFeeCalculator.Calculate(block !.Header, _specProvider.GetSpec(block !.Number + 1)));
            Stack <double> gasUsedRatio = new Stack <double>((int)blockCount);

            Stack <UInt256[]>?rewards = rewardPercentiles is null || rewardPercentiles.Any() is false ? null : new Stack <UInt256[]>((int)blockCount);

            while (block is not null && blockCount > 0)
            {
                oldestBlockNumber = block.Number;
                baseFeePerGas.Push(block.BaseFeePerGas);
                gasUsedRatio.Push(block.GasUsed / (double)block.GasLimit);
                if (rewards is not null)
                {
                    List <UInt256> rewardsInBlock = CalculateRewardsPercentiles(block, rewardPercentiles);
                    if (rewardsInBlock is not null)
                    {
                        rewards.Push(rewardsInBlock.ToArray());
                    }
                }

                blockCount--;
                block = _blockFinder.FindParent(block, BlockTreeLookupOptions.RequireCanonical);
            }

            FeeHistoryResults feeHistoryResults = new(oldestBlockNumber, baseFeePerGas.ToArray(), gasUsedRatio.ToArray(), rewards?.ToArray());

            return(ResultWrapper <FeeHistoryResults> .Success(feeHistoryResults));
        }
Exemplo n.º 22
0
        public static Block GetBlock(this IBlockFinder blockFinder, FilterBlock blockFilter)
        {
            switch (blockFilter.Type)
            {
            case FilterBlockType.Pending:
                return(blockFinder.FindPendingBlock());

            case FilterBlockType.Latest:
                return(blockFinder.FindLatestBlock());

            case FilterBlockType.Earliest:
                return(blockFinder.FindEarliestBlock());

            case FilterBlockType.BlockNumber:
                return(blockFinder.FindBlock(blockFilter.BlockNumber));

            default:
                throw new ArgumentException($"{nameof(FilterBlockType)} not supported: {blockFilter.Type}");
            }
        }
Exemplo n.º 23
0
        public void AddValidTxAndReturnCount_GivenNonEip1559Txs_EffectiveGasPriceProperlyCalculated(bool eip1559Enabled, ulong[] expected)
        {
            Transaction[] nonEip1559TxGroup =
            {
                Build.A.Transaction.WithMaxFeePerGas(27).WithMaxPriorityFeePerGas(25).TestObject,
                Build.A.Transaction.WithMaxFeePerGas(27).WithMaxPriorityFeePerGas(26).TestObject,
                Build.A.Transaction.WithMaxFeePerGas(27).WithMaxPriorityFeePerGas(27).TestObject
            };
            Block        nonEip1559Block = Build.A.Block.Genesis.WithTransactions(nonEip1559TxGroup).WithBaseFeePerGas(1).TestObject;
            IBlockFinder blockFinder     = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(0).Returns(nonEip1559Block);
            GasPriceOracle gasPriceOracle = new(blockFinder, GetSpecProviderWithEip1559EnabledAs(eip1559Enabled));

            IEnumerable <UInt256> results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0);

            List <UInt256> expectedList = expected.Select(n => (UInt256)n).ToList();

            results.Should().BeEquivalentTo(expectedList);
        }
Exemplo n.º 24
0
        public void GetGasPricesFromRecentBlocks_TxsSentByMiner_ShouldNotHaveGasPriceInTxGasPriceList()
        {
            Address minerAddress = TestItem.PrivateKeyA.Address;

            Transaction[] transactions =
            {
                Build.A.Transaction.WithGasPrice(7).SignedAndResolved(TestItem.PrivateKeyA).WithNonce(0).TestObject,
                Build.A.Transaction.WithGasPrice(8).SignedAndResolved(TestItem.PrivateKeyB).WithNonce(0).TestObject,
                Build.A.Transaction.WithGasPrice(9).SignedAndResolved(TestItem.PrivateKeyC).WithNonce(0).TestObject,
            };
            Block        block       = Build.A.Block.Genesis.WithBeneficiary(minerAddress).WithTransactions(transactions).TestObject;
            IBlockFinder blockFinder = Substitute.For <IBlockFinder>();

            blockFinder.FindBlock(0).Returns(block);
            GasPriceOracle gasPriceOracle = new(blockFinder, Substitute.For <ISpecProvider>());
            List <UInt256> expected       = new() { 8, 9 };

            IEnumerable <UInt256> results = gasPriceOracle.GetSortedGasPricesFromRecentBlocks(0);

            results.Should().BeEquivalentTo(expected);
        }
Exemplo n.º 25
0
 public Task <Block?> FindBlockAsync(Keccak blockHash)
 {
     return(Task.FromResult <Block?>(_blockTree.FindBlock(blockHash)));
 }
Exemplo n.º 26
0
        public static Block?RetrieveHeadBlock(this IBlockFinder finder)
        {
            Keccak?headHash = finder.Head?.Hash;

            return(headHash is null ? null : finder.FindBlock(headHash, BlockTreeLookupOptions.None));
        }
Exemplo n.º 27
0
 public static Block RetrieveHeadBlock(this IBlockFinder finder)
 {
     return(finder.FindBlock(finder.Head.Hash, BlockTreeLookupOptions.None));
 }
Exemplo n.º 28
0
 public static Block FindParent(this IBlockFinder finder, BlockHeader blockHeader, BlockTreeLookupOptions options)
 {
     return(finder.FindBlock(blockHeader.ParentHash, options));
 }
Exemplo n.º 29
0
 public Block FindBlock(Keccak blockHash) => _blockFinder.FindBlock(blockHash);