From 4aa61a298135b281f29a0b56266faebf0cb7d722 Mon Sep 17 00:00:00 2001 From: Ratan Rai Sur Date: Thu, 24 Jun 2021 20:42:53 -0500 Subject: [PATCH 1/3] naming and test Signed-off-by: Ratan Rai Sur --- CHANGELOG.md | 5 ++++ .../methods/EthGetTransactionReceipt.java | 10 +++---- .../methods/EthGetTransactionReceiptTest.java | 30 ++++++++++++++++--- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e7834b23e6..0935c17c0d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 21.7.0 + +### Bug Fixes +- Fixed NoSuchElementException with legacy transaction receipts when using eth_getTransactionReceipt [\#2477](https://github.com/hyperledger/besu/pull/2477) + ## 21.7.0-RC2 ### Additions and Improvements diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceipt.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceipt.java index 620febbfb4e..485a368ef16 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceipt.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceipt.java @@ -28,10 +28,10 @@ public class EthGetTransactionReceipt implements JsonRpcMethod { - private final BlockchainQueries blockchain; + private final BlockchainQueries blockchainQueries; - public EthGetTransactionReceipt(final BlockchainQueries blockchain) { - this.blockchain = blockchain; + public EthGetTransactionReceipt(final BlockchainQueries blockchainQueries) { + this.blockchainQueries = blockchainQueries; } @Override @@ -43,9 +43,9 @@ public String getName() { public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { final Hash hash = requestContext.getRequiredParameter(0, Hash.class); final TransactionReceiptResult result = - blockchain + blockchainQueries .transactionReceiptByTransactionHash(hash) - .map(receipt -> getResult(receipt)) + .map(this::getResult) .orElse(null); return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java index 3cc937153f4..f6e0ca3b849 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.TransactionReceiptWithMetadata; import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Transaction; @@ -37,6 +38,7 @@ import org.hyperledger.besu.ethereum.mainnet.PoWHasher; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.plugin.data.TransactionType; import java.math.BigInteger; import java.util.Collections; @@ -47,7 +49,7 @@ public class EthGetTransactionReceiptTest { - private final TransactionReceipt stateReceipt = + private final TransactionReceipt statusReceipt = new TransactionReceipt(1, 12, Collections.emptyList(), Optional.empty()); private final Hash stateRoot = Hash.fromHexString("0000000000000000000000000000000000000000000000000000000000000000"); @@ -76,9 +78,9 @@ public class EthGetTransactionReceiptTest { private final Hash blockHash = Hash.fromHexString("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); - private final TransactionReceiptWithMetadata stateReceiptWithMetaData = + private final TransactionReceiptWithMetadata statusReceiptWithMetadata = TransactionReceiptWithMetadata.create( - stateReceipt, transaction, hash, 1, 2, Optional.empty(), blockHash, 4); + statusReceipt, transaction, hash, 1, 2, Optional.empty(), blockHash, 4); private final TransactionReceiptWithMetadata rootReceiptWithMetaData = TransactionReceiptWithMetadata.create( rootReceipt, transaction, hash, 1, 2, Optional.empty(), blockHash, 4); @@ -152,7 +154,7 @@ public class EthGetTransactionReceiptTest { public void shouldCreateAStatusTransactionReceiptWhenStatusTypeProtocol() { when(blockchain.headBlockNumber()).thenReturn(1L); when(blockchain.transactionReceiptByTransactionHash(receiptHash)) - .thenReturn(Optional.of(stateReceiptWithMetaData)); + .thenReturn(Optional.of(statusReceiptWithMetadata)); when(protocolSchedule.getByBlockNumber(1)).thenReturn(statusTransactionTypeSpec); final JsonRpcSuccessResponse response = @@ -176,4 +178,24 @@ public void shouldCreateARootTransactionReceiptWhenRootTypeProtocol() { assertThat(result.getRoot()).isEqualTo(stateRoot.toString()); } + + @Test + public void shouldWorkFor1559Txs() { + when(blockchain.headBlockNumber()).thenReturn(1L); + final Transaction transaction1559 = + new BlockDataGenerator().transaction(TransactionType.EIP1559); + final TransactionReceiptWithMetadata transactionReceiptWithMetadata = + TransactionReceiptWithMetadata.create( + statusReceipt, transaction1559, hash, 1, 2, Optional.of(1L), blockHash, 4); + when(blockchain.transactionReceiptByTransactionHash(receiptHash)) + .thenReturn(Optional.of(transactionReceiptWithMetadata)); + when(protocolSchedule.getByBlockNumber(1)).thenReturn(rootTransactionTypeSpec); + + final JsonRpcSuccessResponse response = + (JsonRpcSuccessResponse) ethGetTransactionReceipt.response(request); + final TransactionReceiptStatusResult result = + (TransactionReceiptStatusResult) response.getResult(); + + assertThat(result.getStatus()).isEqualTo("0x1"); + } } From aecc10e30206c6b363f27637fce576ab87d12271 Mon Sep 17 00:00:00 2001 From: Ratan Rai Sur Date: Thu, 24 Jun 2021 21:05:45 -0500 Subject: [PATCH 2/3] new version Signed-off-by: Ratan Rai Sur --- CHANGELOG.md | 2 +- .../methods/EthGetMinerDataByBlockHash.java | 2 +- .../results/TransactionReceiptResult.java | 2 +- .../methods/EthGetTransactionReceiptTest.java | 8 ++++++- .../besu/ethereum/core/Transaction.java | 21 +++++++------------ .../besu/ethstats/EthStatsService.java | 4 ++-- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0935c17c0d2..d7168781932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## 21.7.0 ### Bug Fixes -- Fixed NoSuchElementException with legacy transaction receipts when using eth_getTransactionReceipt [\#2477](https://github.com/hyperledger/besu/pull/2477) +- Fixed NoSuchElementException with EIP1559 transaction receipts when using eth_getTransactionReceipt [\#2477](https://github.com/hyperledger/besu/pull/2477) ## 21.7.0-RC2 diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java index b248bda1222..203f25d6a87 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java @@ -91,7 +91,7 @@ public static MinerDataResult createMinerDataResult( receipt -> receipt .getTransaction() - .calcEffectiveGas(receipt.getBaseFee()) + .getEffectiveGasPrice(receipt.getBaseFee()) .multiply(receipt.getGasUsed())) .orElse(Wei.ZERO)) .reduce(Wei.ZERO, BaseUInt256Value::add); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionReceiptResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionReceiptResult.java index 5f22df8b8b7..bf4edf3b138 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionReceiptResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionReceiptResult.java @@ -74,7 +74,7 @@ protected TransactionReceiptResult(final TransactionReceiptWithMetadata receiptW this.from = txn.getSender().toString(); this.gasUsed = Quantity.create(receiptWithMetadata.getGasUsed()); this.effectiveGasPrice = - Quantity.create(txn.calcEffectiveGas(receiptWithMetadata.getBaseFee())); + Quantity.create(txn.getEffectiveGasPrice(receiptWithMetadata.getBaseFee())); this.logs = logReceipts( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java index f6e0ca3b849..5e02ee6f076 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java @@ -184,9 +184,10 @@ public void shouldWorkFor1559Txs() { when(blockchain.headBlockNumber()).thenReturn(1L); final Transaction transaction1559 = new BlockDataGenerator().transaction(TransactionType.EIP1559); + final long baseFee = 1L; final TransactionReceiptWithMetadata transactionReceiptWithMetadata = TransactionReceiptWithMetadata.create( - statusReceipt, transaction1559, hash, 1, 2, Optional.of(1L), blockHash, 4); + statusReceipt, transaction1559, hash, 1, 2, Optional.of(baseFee), blockHash, 4); when(blockchain.transactionReceiptByTransactionHash(receiptHash)) .thenReturn(Optional.of(transactionReceiptWithMetadata)); when(protocolSchedule.getByBlockNumber(1)).thenReturn(rootTransactionTypeSpec); @@ -197,5 +198,10 @@ public void shouldWorkFor1559Txs() { (TransactionReceiptStatusResult) response.getResult(); assertThat(result.getStatus()).isEqualTo("0x1"); + assertThat(Long.decode(result.getEffectiveGasPrice())) + .isEqualTo( + Math.min( + baseFee + transaction1559.getMaxPriorityFeePerGas().get().toLong(), + transaction1559.getMaxFeePerGas().get().toLong())); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index e99a9cec753..97d6b78165e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -33,6 +33,7 @@ import java.math.BigInteger; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -1006,22 +1007,14 @@ SECPSignature computeSignature(final KeyPair keys) { * @param baseFeePerGas optional baseFee from the block header, if we are post-london * @return the effective gas price. */ - public final Wei calcEffectiveGas(final Optional baseFeePerGas) { + public final Wei getEffectiveGasPrice(final Optional baseFeePerGas) { return baseFeePerGas .filter(fee -> getType().supports1559FeeMarket()) - .map(BigInteger::valueOf) - .flatMap( + .map( baseFee -> - getMaxFeePerGas() - .map(org.hyperledger.besu.plugin.data.Quantity::getAsBigInteger) - .flatMap( - maxFeePerGas -> - getMaxPriorityFeePerGas() - .map(org.hyperledger.besu.plugin.data.Quantity::getAsBigInteger) - .map( - maxPriorityFeePerGas -> - baseFee.add(maxPriorityFeePerGas).min(maxFeePerGas)))) - .map(Wei::ofNumber) - .orElse(getGasPrice().get()); + Collections.min( + Arrays.asList( + getMaxFeePerGas().get(), getMaxPriorityFeePerGas().get().add(baseFee)))) + .orElseGet(() -> getGasPrice().get()); } } diff --git a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java index ad87e9a74b0..16374dfa9df 100644 --- a/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java +++ b/ethereum/ethstats/src/main/java/org/hyperledger/besu/ethstats/EthStatsService.java @@ -438,8 +438,8 @@ private long suggestGasPrice(final Block block) { // retrieves transactions from the last blocks and takes the lowest gas price. If no transaction // is present we return the minTransactionGasPrice of the mining coordinator return block.getBody().getTransactions().stream() - .min(Comparator.comparing(t -> t.calcEffectiveGas(block.getHeader().getBaseFee()))) - .map(t -> t.calcEffectiveGas(block.getHeader().getBaseFee())) + .min(Comparator.comparing(t -> t.getEffectiveGasPrice(block.getHeader().getBaseFee()))) + .map(t -> t.getEffectiveGasPrice(block.getHeader().getBaseFee())) .filter(wei -> wei.getValue().longValue() > 0) .orElse(miningCoordinator.getMinTransactionGasPrice()) .getValue() From 7583c7949f775ef206bf35965bf19b5bb6c64741 Mon Sep 17 00:00:00 2001 From: Ratan Rai Sur Date: Fri, 25 Jun 2021 11:03:53 -0500 Subject: [PATCH 3/3] repurpose effective priority fee Signed-off-by: Ratan Rai Sur --- .../hyperledger/besu/ethereum/core/Transaction.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index 97d6b78165e..dbeed6a64aa 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -33,7 +33,6 @@ import java.math.BigInteger; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -1008,13 +1007,6 @@ SECPSignature computeSignature(final KeyPair keys) { * @return the effective gas price. */ public final Wei getEffectiveGasPrice(final Optional baseFeePerGas) { - return baseFeePerGas - .filter(fee -> getType().supports1559FeeMarket()) - .map( - baseFee -> - Collections.min( - Arrays.asList( - getMaxFeePerGas().get(), getMaxPriorityFeePerGas().get().add(baseFee)))) - .orElseGet(() -> getGasPrice().get()); + return Wei.of(getEffectivePriorityFeePerGas(baseFeePerGas) + baseFeePerGas.orElse(0L)); } }