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); } } } }
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)); }
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; } } } }
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); }
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); } } } }
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())); }
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)); }
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); }
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); }
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); }
private bool TryGetParentBlock(Block currentBlock, out Block parentBlock) { if (currentBlock.IsGenesis) { parentBlock = null; return(false); } else { parentBlock = _blockFinder.FindBlock(currentBlock.ParentHash); return(true); } }
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); }
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); }
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()); }
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);
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)); }
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}"); } }
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); }
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); }
public Task <Block?> FindBlockAsync(Keccak blockHash) { return(Task.FromResult <Block?>(_blockTree.FindBlock(blockHash))); }
public static Block?RetrieveHeadBlock(this IBlockFinder finder) { Keccak?headHash = finder.Head?.Hash; return(headHash is null ? null : finder.FindBlock(headHash, BlockTreeLookupOptions.None)); }
public static Block RetrieveHeadBlock(this IBlockFinder finder) { return(finder.FindBlock(finder.Head.Hash, BlockTreeLookupOptions.None)); }
public static Block FindParent(this IBlockFinder finder, BlockHeader blockHeader, BlockTreeLookupOptions options) { return(finder.FindBlock(blockHeader.ParentHash, options)); }
public Block FindBlock(Keccak blockHash) => _blockFinder.FindBlock(blockHash);