Skip to content

Commit

Permalink
allow empty maxFeePerBlobGas for eth_call (hyperledger#6731)
Browse files Browse the repository at this point in the history
* allow empty blob gas for eth_call

* handle empty maxFeePerBlobGas by setting to blobBaseFee if empty

* set allowExceedingBalance if blobGas not specified

* added a test case for strict with zero blob gas

Signed-off-by: Sally MacFarlane <[email protected]>

---------

Signed-off-by: Sally MacFarlane <[email protected]>
Co-authored-by: Justin Florentine <[email protected]>
  • Loading branch information
2 people authored and matthew1001 committed Jun 7, 2024
1 parent 7ad28ef commit a54c272
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 23 deletions.
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@
### Additions and Improvements
- `txpool_besuPendingTransactions`change parameter `numResults` to optional parameter [#6708](https://github.com/hyperledger/besu/pull/6708)
- Extend `Blockchain` service [#6592](https://github.com/hyperledger/besu/pull/6592)
- Add bft-style blockperiodseconds transitions to Clique [#6596](https://github.com/hyperledger/besu/pull/6596)
- Add createemptyblocks transitions to Clique [#6608](https://github.com/hyperledger/besu/pull/6608)
- Add bft-style `blockperiodseconds` transitions to Clique [#6596](https://github.com/hyperledger/besu/pull/6596)
- Add `createemptyblocks` transitions to Clique [#6608](https://github.com/hyperledger/besu/pull/6608)
- RocksDB database metadata refactoring [#6555](https://github.com/hyperledger/besu/pull/6555)
- Make layered txpool aware of minGasPrice and minPriorityFeePerGas dynamic options [#6611](https://github.com/hyperledger/besu/pull/6611)
- Make layered txpool aware of `minGasPrice` and `minPriorityFeePerGas` dynamic options [#6611](https://github.com/hyperledger/besu/pull/6611)
- Update commons-compress to 1.26.0 [#6648](https://github.com/hyperledger/besu/pull/6648)
- Update Vert.x to 4.5.4 [#6666](https://github.com/hyperledger/besu/pull/6666)
- Refactor and extend `TransactionPoolValidatorService` [#6636](https://github.com/hyperledger/besu/pull/6636)
- Transaction call object to accept both `input` and `data` field simultaneously if they are set to equal values [#6702](https://github.com/hyperledger/besu/pull/6702)
- Introduce `TransactionSimulationService` [#6686](https://github.com/hyperledger/besu/pull/6686)
- Transaction call object to accept both `input` and `data` field simultaneously if they are set to equal values [#6702](https://github.com/hyperledger/besu/pull/6702)
- `eth_call` for blob tx allows for empty `maxFeePerBlobGas` [#6731](https://github.com/hyperledger/besu/pull/6731)

### Bug fixes
- Fix txpool dump/restore race condition [#6665](https://github.com/hyperledger/besu/pull/6665)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ private boolean isAllowExceedingBalanceAutoSelection(
callParams.getGasPrice() == null || Wei.ZERO.equals(callParams.getGasPrice());

if (header.getBaseFee().isPresent()) {
if (callParams.getBlobVersionedHashes().isPresent()
&& (callParams.getMaxFeePerBlobGas().isEmpty()
|| callParams.getMaxFeePerBlobGas().get().equals(Wei.ZERO))) {
return true;
}
boolean isZeroMaxFeePerGas = callParams.getMaxFeePerGas().orElse(Wei.ZERO).equals(Wei.ZERO);
boolean isZeroMaxPriorityFeePerGas =
callParams.getMaxPriorityFeePerGas().orElse(Wei.ZERO).equals(Wei.ZERO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"response": {
"jsonrpc": "2.0",
"id": 4,
"error":{"code":-32603,"message":"Internal error"}
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
"statusCode": 200
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"request": {
"id": 4,
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"data": "0x12a7b914",
"blobVersionedHashes" : ["0x0100000051c8833cfbaf272e62da1285b183b0405357f62b052a4894ffcdaa2d"],
"gasPrice": "0x000000000000000000000000000000000000000000000000000000003437004a",
"maxFeePerBlobGas": "0x0000000000000000000000000000000000000000000000000000000000000000",
"strict": true
},
"latest"
]
},
"response": {
"jsonrpc": "2.0",
"id": 4,
"error":{"code":-32009,"message":"blob gas price below current blob base fee"}
},
"statusCode": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"response": {
"jsonrpc": "2.0",
"id": 4,
"error":{"code":-32009,"message":"blob gas price below current blob base fee"}
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
},
"statusCode": 200
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,13 @@ private ValidationResult<TransactionInvalidReason> validateCostAndFee(
if (maybeBlobFee.isEmpty()) {
throw new IllegalArgumentException(
"blob fee must be provided from blocks containing blobs");
// tx.getMaxFeePerBlobGas can be empty for eth_call
} else if (!transactionValidationParams.allowUnderpriced()
&& maybeBlobFee.get().compareTo(transaction.getMaxFeePerBlobGas().get()) > 0) {
return ValidationResult.invalid(
TransactionInvalidReason.BLOB_GAS_PRICE_BELOW_CURRENT_BLOB_BASE_FEE,
String.format(
"max fee per blob gas less than block blob gas fee: address %s blobGasFeeCap: %s, blobBaseFee: %s",
"tx max fee per blob gas less than block blob gas fee: address %s blobGasFeeCap: %s, blobBaseFee: %s",
transaction.getSender().toHexString(),
transaction.getMaxFeePerBlobGas().get().toHumanReadableString(),
maybeBlobFee.get().toHumanReadableString()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import org.apache.tuweni.bytes.Bytes;

// Represents parameters for a eth_call or eth_estimateGas JSON-RPC methods.
// Represents parameters for eth_call and eth_estimateGas JSON-RPC methods.
public class CallParameter {

private final Address from;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,18 @@ public Optional<TransactionSimulatorResult> processWithWorldUpdater(
final MainnetTransactionProcessor transactionProcessor =
protocolSchedule.getByBlockHeader(blockHeaderToProcess).getTransactionProcessor();

final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(blockHeaderToProcess.getParentHash());
final Wei blobGasPrice =
transactionValidationParams.isAllowExceedingBalance()
? Wei.ZERO
: protocolSpec
.getFeeMarket()
.blobGasPricePerGas(
maybeParentHeader
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));

final Optional<Transaction> maybeTransaction =
buildTransaction(
callParams,
Expand All @@ -256,21 +268,12 @@ public Optional<TransactionSimulatorResult> processWithWorldUpdater(
nonce,
gasLimit,
value,
payload);
payload,
blobGasPrice);
if (maybeTransaction.isEmpty()) {
return Optional.empty();
}

final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(blockHeaderToProcess.getParentHash());
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.blobGasPricePerGas(
maybeParentHeader
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));

final Transaction transaction = maybeTransaction.get();
final TransactionProcessingResult result =
transactionProcessor.processTransaction(
Expand Down Expand Up @@ -298,7 +301,8 @@ private Optional<Transaction> buildTransaction(
final long nonce,
final long gasLimit,
final Wei value,
final Bytes payload) {
final Bytes payload,
final Wei blobGasPrice) {
final Transaction.Builder transactionBuilder =
Transaction.builder()
.nonce(nonce)
Expand All @@ -313,20 +317,21 @@ private Optional<Transaction> buildTransaction(
callParams.getAccessList().ifPresent(transactionBuilder::accessList);
// Set versioned hashes if present
callParams.getBlobVersionedHashes().ifPresent(transactionBuilder::versionedHashes);
// Set max fee per blob gas if present
callParams.getMaxFeePerBlobGas().ifPresent(transactionBuilder::maxFeePerBlobGas);

final Wei gasPrice;
final Wei maxFeePerGas;
final Wei maxPriorityFeePerGas;
final Wei maxFeePerBlobGas;
if (transactionValidationParams.isAllowExceedingBalance()) {
gasPrice = Wei.ZERO;
maxFeePerGas = Wei.ZERO;
maxPriorityFeePerGas = Wei.ZERO;
maxFeePerBlobGas = Wei.ZERO;
} else {
gasPrice = callParams.getGasPrice() != null ? callParams.getGasPrice() : Wei.ZERO;
maxFeePerGas = callParams.getMaxFeePerGas().orElse(gasPrice);
maxPriorityFeePerGas = callParams.getMaxPriorityFeePerGas().orElse(gasPrice);
maxFeePerBlobGas = callParams.getMaxFeePerBlobGas().orElse(blobGasPrice);
}
if (header.getBaseFee().isEmpty()) {
transactionBuilder.gasPrice(gasPrice);
Expand All @@ -337,6 +342,9 @@ private Optional<Transaction> buildTransaction(
}

transactionBuilder.guessType();
if (transactionBuilder.getTransactionType().supportsBlob()) {
transactionBuilder.maxFeePerBlobGas(maxFeePerBlobGas);
}
if (transactionBuilder.getTransactionType().requiresChainId()) {
transactionBuilder.chainId(
protocolSchedule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ public void shouldRejectTransactionWithMaxBlobPriorityFeeSmallerThanBlobBaseFee(
.isEqualTo(ValidationResult.invalid(BLOB_GAS_PRICE_BELOW_CURRENT_BLOB_BASE_FEE));
assertThat(validationResult.getErrorMessage())
.matches(
"max fee per blob gas less than block blob gas fee: address 0x[0-9a-f]+ blobGasFeeCap: 7 wei, blobBaseFee: 10 wei");
"tx max fee per blob gas less than block blob gas fee: address 0x[0-9a-f]+ blobGasFeeCap: 7 wei, blobBaseFee: 10 wei");
}

@Test
Expand Down

0 comments on commit a54c272

Please sign in to comment.