Improve test coverage of autoselection of isAllowedExeceedingBalance validation parameter (#2938)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: Gary Schulte <gary.schulte@consensys.net>
pull/2941/head
fab-10 3 years ago committed by GitHub
parent 9deb5ea5d2
commit f58ca8da94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 53
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java
  2. 73
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java

@ -147,38 +147,37 @@ public class EthCall extends AbstractBlockParameterOrBlockHashMethod {
// if it is not set explicitly whether we want a strict check of the balance or not. this will // if it is not set explicitly whether we want a strict check of the balance or not. this will
// be decided according to the provided parameters // be decided according to the provided parameters
if (callParams.isMaybeStrict().isEmpty()) { if (callParams.isMaybeStrict().isEmpty()) {
transactionValidationParams.isAllowExceedingBalance(
boolean isZeroGasPrice = isAllowExeedingBalanceAutoSelection(header, callParams));
callParams.getGasPrice() == null || Wei.ZERO.equals(callParams.getGasPrice());
header
.getBaseFee()
.ifPresentOrElse(
__ -> {
boolean isZeroMaxFeePerGas =
callParams.getMaxFeePerGas().orElse(Wei.ZERO).equals(Wei.ZERO);
boolean isZeroMaxPriorityFeePerGas =
callParams.getMaxPriorityFeePerGas().orElse(Wei.ZERO).equals(Wei.ZERO);
if (isZeroGasPrice && isZeroMaxFeePerGas && isZeroMaxPriorityFeePerGas) {
// After 1559, when gas pricing is not provided, 0 is used and the balance is not
// checked
transactionValidationParams.isAllowExceedingBalance(true);
} else {
// After 1559, when gas price is provided, it is interpreted as both the max and
// priority fee and the balance is checked
transactionValidationParams.isAllowExceedingBalance(false);
}
},
() -> {
// Prior 1559, when gas price == 0 or is not provided the balance is not checked
transactionValidationParams.isAllowExceedingBalance(isZeroGasPrice);
});
} else { } else {
transactionValidationParams.isAllowExceedingBalance( transactionValidationParams.isAllowExceedingBalance(
!callParams.isMaybeStrict().orElse(Boolean.FALSE)); !callParams.isMaybeStrict().orElse(Boolean.FALSE));
} }
return transactionValidationParams.build(); return transactionValidationParams.build();
} }
private boolean isAllowExeedingBalanceAutoSelection(
final BlockHeader header, final JsonCallParameter callParams) {
boolean isZeroGasPrice =
callParams.getGasPrice() == null || Wei.ZERO.equals(callParams.getGasPrice());
if (header.getBaseFee().isPresent()) {
boolean isZeroMaxFeePerGas = callParams.getMaxFeePerGas().orElse(Wei.ZERO).equals(Wei.ZERO);
boolean isZeroMaxPriorityFeePerGas =
callParams.getMaxPriorityFeePerGas().orElse(Wei.ZERO).equals(Wei.ZERO);
if (isZeroGasPrice && isZeroMaxFeePerGas && isZeroMaxPriorityFeePerGas) {
// After 1559, when gas pricing is not provided, 0 is used and the balance is not
// checked
return true;
} else {
// After 1559, when gas price is provided, it is interpreted as both the max and
// priority fee and the balance is checked
return false;
}
}
// Prior 1559, when gas price == 0 or is not provided the balance is not checked
return isZeroGasPrice;
}
} }

@ -40,6 +40,8 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.ChainHead; import org.hyperledger.besu.ethereum.chain.ChainHead;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
@ -215,14 +217,79 @@ public class EthCallTest {
verify(blockchainQueries).headBlockNumber(); verify(blockchainQueries).headBlockNumber();
} }
@Test
public void shouldAutoSelectIsAllowedExeceedingBalanceToTrueWhenGasPriceIsZero() {
JsonCallParameter callParameters = callParameter(Wei.ZERO, null, null);
internalAutoSelectIsAllowedExeecdBalance(callParameters, Optional.empty(), true);
}
@Test
public void shouldAutoSelectIsAllowedExeceedingBalanceToTrueWhenGasPriceIsZeroAfterEIP1559() {
JsonCallParameter callParameters = callParameter(Wei.ZERO, null, null);
internalAutoSelectIsAllowedExeecdBalance(callParameters, Optional.of(1L), true);
}
@Test
public void shouldAutoSelectIsAllowedExeceedingBalanceToFalseWhenGasPriceIsNotZero() {
JsonCallParameter callParameters = callParameter(Wei.ONE, null, null);
internalAutoSelectIsAllowedExeecdBalance(callParameters, Optional.empty(), false);
}
@Test
public void shouldAutoSelectIsAllowedExeceedingBalanceToFalseWhenGasPriceIsNotZeroAfterEIP1559() {
JsonCallParameter callParameters = callParameter(Wei.ONE, null, null);
internalAutoSelectIsAllowedExeecdBalance(callParameters, Optional.of(1L), false);
}
@Test
public void shouldAutoSelectIsAllowedExeceedingBalanceToTrueWhenFeesAreZero() {
JsonCallParameter callParameters = callParameter(null, Wei.ZERO, Wei.ZERO);
internalAutoSelectIsAllowedExeecdBalance(callParameters, Optional.of(1L), true);
}
@Test
public void shouldAutoSelectIsAllowedExeceedingBalanceToFalseWhenFeesAreZero() {
JsonCallParameter callParameters = callParameter(null, Wei.ONE, Wei.ONE);
internalAutoSelectIsAllowedExeecdBalance(callParameters, Optional.of(1L), false);
}
private void internalAutoSelectIsAllowedExeecdBalance(
final JsonCallParameter callParameter,
final Optional<Long> baseFee,
final boolean isAllowedExeedingBalance) {
final JsonRpcRequestContext request = ethCallRequest(callParameter, "latest");
BlockHeader blockHeader = mock(BlockHeader.class);
when(blockHeader.getBaseFee()).thenReturn(baseFee);
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchainQueries.getBlockchain().getChainHead()).thenReturn(chainHead);
when(blockchainQueries.getBlockchain().getChainHead().getHash()).thenReturn(Hash.ZERO);
when(blockchainQueries.getBlockHeaderByHash(Hash.ZERO)).thenReturn(Optional.of(blockHeader));
method.response(request);
TransactionValidationParams transactionValidationParams =
ImmutableTransactionValidationParams.builder()
.from(TransactionValidationParams.transactionSimulator())
.isAllowExceedingBalance(isAllowedExeedingBalance)
.build();
verify(transactionSimulator).process(any(), eq(transactionValidationParams), any(), any());
}
private JsonCallParameter callParameter() { private JsonCallParameter callParameter() {
return callParameter(Wei.ZERO, null, null);
}
private JsonCallParameter callParameter(
final Wei gasPrice, final Wei maxFeesPerGas, final Wei maxPriorityFeesPerGas) {
return new JsonCallParameter( return new JsonCallParameter(
Address.fromHexString("0x0"), Address.fromHexString("0x0"),
Address.fromHexString("0x0"), Address.fromHexString("0x0"),
Gas.ZERO, Gas.ZERO,
Wei.ZERO, gasPrice,
null, maxFeesPerGas,
null, maxPriorityFeesPerGas,
Wei.ZERO, Wei.ZERO,
Bytes.EMPTY, Bytes.EMPTY,
null); null);

Loading…
Cancel
Save