Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow frontier simulation when Base Fee is present #7965

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
### Additions and Improvements

### Bug fixes
- Correct default parameters for frontier transactions in `eth_call` and `eth_estimateGas` [#7965](https://github.com/hyperledger/besu/pull/7965)

## 24.12.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public void shouldReturnErrorWithInvalidChainId() {
.withChainId(BLOCKCHAIN.getChainId().add(BigInteger.ONE))
.withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))
.withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"))
.withMaxFeePerGas(Wei.ONE)
.withValue(Wei.ONE)
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,6 @@ public Optional<TransactionSimulatorResult> processWithWorldUpdater(
final long simulationGasCap =
calculateSimulationGasCap(callParams.getGasLimit(), blockHeaderToProcess.getGasLimit());

final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO;
final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY;

final MainnetTransactionProcessor transactionProcessor =
protocolSchedule.getByBlockHeader(blockHeaderToProcess).getTransactionProcessor();

Expand All @@ -322,8 +319,6 @@ public Optional<TransactionSimulatorResult> processWithWorldUpdater(
senderAddress,
nonce,
simulationGasCap,
value,
payload,
blobGasPrice);
if (maybeTransaction.isEmpty()) {
return Optional.empty();
Expand Down Expand Up @@ -404,9 +399,11 @@ private Optional<Transaction> buildTransaction(
final Address senderAddress,
final long nonce,
final long gasLimit,
final Wei value,
final Bytes payload,
final Wei blobGasPrice) {

final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO;
final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY;

final Transaction.Builder transactionBuilder =
Transaction.builder()
.nonce(nonce)
Expand Down Expand Up @@ -437,18 +434,21 @@ private Optional<Transaction> buildTransaction(
maxPriorityFeePerGas = callParams.getMaxPriorityFeePerGas().orElse(gasPrice);
maxFeePerBlobGas = callParams.getMaxFeePerBlobGas().orElse(blobGasPrice);
}
if (header.getBaseFee().isEmpty()) {

if (shouldSetGasPrice(callParams, header)) {
transactionBuilder.gasPrice(gasPrice);
} else if (protocolSchedule.getChainId().isPresent()) {
}

if (shouldSetMaxFeePerGas(callParams, header)) {
transactionBuilder.maxFeePerGas(maxFeePerGas).maxPriorityFeePerGas(maxPriorityFeePerGas);
} else {
return Optional.empty();
}

transactionBuilder.guessType();
if (transactionBuilder.getTransactionType().supportsBlob()) {
if (shouldSetBlobGasPrice(callParams)) {
transactionBuilder.maxFeePerBlobGas(maxFeePerBlobGas);
}

transactionBuilder.guessType();

if (transactionBuilder.getTransactionType().requiresChainId()) {
callParams
.getChainId()
Expand Down Expand Up @@ -489,4 +489,39 @@ public Optional<Boolean> doesAddressExist(

return Optional.of(worldState.get(address) != null);
}

private boolean shouldSetGasPrice(final CallParameter callParams, final BlockHeader header) {
if (header.getBaseFee().isEmpty()) {
return true;
}

// if maxPriorityFeePerGas and maxFeePerGas are not set, use gasPrice
return callParams.getMaxPriorityFeePerGas().isEmpty() && callParams.getMaxFeePerGas().isEmpty();
}

private boolean shouldSetMaxFeePerGas(final CallParameter callParams, final BlockHeader header) {
if (protocolSchedule.getChainId().isEmpty()) {
return false;
}

if (header.getBaseFee().isEmpty()) {
return false;
}

if (shouldSetBlobGasPrice(callParams)) {
return true;
}

// only set maxFeePerGas and maxPriorityFeePerGas if they are present, otherwise transaction
// will be considered EIP-1559 transaction even if the simulation is for a legacy transaction
return callParams.getMaxPriorityFeePerGas().isPresent()
|| callParams.getMaxFeePerGas().isPresent();
}

private boolean shouldSetBlobGasPrice(final CallParameter callParams) {
if (protocolSchedule.getChainId().isEmpty()) {
return false;
}
return callParams.getBlobVersionedHashes().isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -912,4 +912,43 @@ private CallParameter blobTransactionCallParameter(
Optional.of(maxFeePerBlobGas),
Optional.of(bwc.getVersionedHashes()));
}

@Test
public void shouldSimulateLegacyTransactionWhenBaseFeeNotZero() {
// tests that the transaction simulator will simulate a legacy transaction when the base fee is
// not zero
// and the transaction is a legacy transaction

final CallParameter callParameter = legacyTransactionCallParameter();

final BlockHeader blockHeader =
blockHeaderTestFixture
.number(1L)
.stateRoot(Hash.ZERO)
.baseFeePerGas(Wei.of(7))
.buildHeader();

mockBlockchainForBlockHeader(blockHeader);
mockWorldStateForAccount(blockHeader, callParameter.getFrom(), 1L);

final Transaction expectedTransaction =
Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(1L)
.gasPrice(callParameter.getGasPrice())
.gasLimit(blockHeader.getGasLimit())
.to(callParameter.getTo())
.sender(callParameter.getFrom())
.value(callParameter.getValue())
.payload(callParameter.getPayload())
.signature(FAKE_SIGNATURE)
.build();
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);

final Optional<TransactionSimulatorResult> result =
transactionSimulator.process(callParameter, 1L);

verifyTransactionWasProcessed(expectedTransaction);
assertThat(result.get().isSuccessful()).isTrue();
}
}
Loading