Skip to content

Commit

Permalink
EIP-3860 Initcode Size Reference Test fixes (hyperledger#4911)
Browse files Browse the repository at this point in the history
* EIP-3860 Initcode Size Reference Test fixes

Fix corner cases around initcode size checking in reference tests.

Signed-off-by: Danno Ferrin <danno.ferrin@swirldslabs.com>
  • Loading branch information
shemnon authored and siladu committed Jan 14, 2023
1 parent 0455b22 commit 901573c
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public abstract class MainnetProtocolSpecs {
public static final int FRONTIER_CONTRACT_SIZE_LIMIT = Integer.MAX_VALUE;

public static final int SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT = 24576;
public static final int SHANGHAI_CONTRACT_SIZE_LIMIT = 2 * SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT;
public static final int SHANGHAI_INIT_CODE_SIZE_LIMIT = 2 * SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT;
public static final int SHANDONG_CONTRACT_SIZE_LIMIT = 2 * SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT;

private static final Address RIPEMD160_PRECOMPILE =
Expand Down Expand Up @@ -534,7 +534,8 @@ static ProtocolSpecBuilder londonDefinition(
TransactionType.FRONTIER,
TransactionType.ACCESS_LIST,
TransactionType.EIP1559),
quorumCompatibilityMode))
quorumCompatibilityMode,
Integer.MAX_VALUE))
.transactionProcessorBuilder(
(gasCalculator,
transactionValidator,
Expand Down Expand Up @@ -651,7 +652,6 @@ static ProtocolSpecBuilder shanghaiDefinition(

final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
final BaseFeeMarket baseFeeMarket = getBaseFeeMarket(genesisConfigOptions);
final int contractSizeLimit = configContractSizeLimit.orElse(SHANGHAI_CONTRACT_SIZE_LIMIT);

return parisDefinition(
chainId,
Expand Down Expand Up @@ -681,15 +681,20 @@ static ProtocolSpecBuilder shanghaiDefinition(
stackSizeLimit,
baseFeeMarket,
CoinbaseFeePriceCalculator.eip1559()))
.contractCreationProcessorBuilder(
(gasCalculator, evm) ->
new ContractCreationProcessor(
// Contract creation rules for EIP-3860 Limit and meter intitcode
.transactionValidatorBuilder(
gasCalculator ->
new MainnetTransactionValidator(
gasCalculator,
evm,
baseFeeMarket,
true,
List.of(MaxCodeSizeRule.of(contractSizeLimit), PrefixCodeRule.of()),
1,
SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES))
chainId,
Set.of(
TransactionType.FRONTIER,
TransactionType.ACCESS_LIST,
TransactionType.EIP1559),
quorumCompatibilityMode,
SHANGHAI_INIT_CODE_SIZE_LIMIT))
.withdrawalsProcessorBuilder(WithdrawalsProcessor.AllowedWithdrawalsProcessor::new)
.withdrawalsValidatorBuilder(WithdrawalsValidator.AllowedWithdrawals::new)
.name("Shanghai");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public class MainnetTransactionValidator {
private final Set<TransactionType> acceptedTransactionTypes;
private final boolean goQuorumCompatibilityMode;

private final int maxInitcodeSize;

public MainnetTransactionValidator(
final GasCalculator gasCalculator,
final boolean checkSignatureMalleability,
Expand All @@ -78,7 +80,8 @@ public MainnetTransactionValidator(
checkSignatureMalleability,
chainId,
acceptedTransactionTypes,
quorumCompatibilityMode);
quorumCompatibilityMode,
Integer.MAX_VALUE);
}

public MainnetTransactionValidator(
Expand All @@ -87,13 +90,15 @@ public MainnetTransactionValidator(
final boolean checkSignatureMalleability,
final Optional<BigInteger> chainId,
final Set<TransactionType> acceptedTransactionTypes,
final boolean goQuorumCompatibilityMode) {
final boolean goQuorumCompatibilityMode,
final int maxInitcodeSize) {
this.gasCalculator = gasCalculator;
this.feeMarket = feeMarket;
this.disallowSignatureMalleability = checkSignatureMalleability;
this.chainId = chainId;
this.acceptedTransactionTypes = acceptedTransactionTypes;
this.goQuorumCompatibilityMode = goQuorumCompatibilityMode;
this.maxInitcodeSize = maxInitcodeSize;
}

/**
Expand Down Expand Up @@ -184,6 +189,14 @@ public ValidationResult<TransactionInvalidReason> validate(
intrinsicGasCost, transaction.getGasLimit()));
}

if (transaction.isContractCreation() && transaction.getPayload().size() > maxInitcodeSize) {
return ValidationResult.invalid(
TransactionInvalidReason.INITCODE_TOO_LARGE,
String.format(
"Initcode size of %d exceeds maximum size of %s",
transaction.getPayload().size(), maxInitcodeSize));
}

return ValidationResult.valid();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum TransactionInvalidReason {
TRANSACTION_ALREADY_KNOWN,
TRANSACTION_REPLACEMENT_UNDERPRICED,
MAX_PRIORITY_FEE_PER_GAS_EXCEEDS_MAX_FEE_PER_GAS,
INITCODE_TOO_LARGE,
// Private Transaction Invalid Reasons
PRIVATE_TRANSACTION_FAILED,
PRIVATE_NONCE_TOO_LOW,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
import java.math.BigInteger;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
Expand Down Expand Up @@ -259,7 +259,8 @@ public void shouldRejectTransactionWithMaxPriorityFeeGreaterThanMaxFee() {
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.values()),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);
validator.setTransactionFilter(transactionFilter(true));

final Transaction transaction =
Expand Down Expand Up @@ -342,7 +343,8 @@ public void shouldAcceptOnlyTransactionsInAcceptedTransactionTypes() {
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);

final MainnetTransactionValidator eip1559Validator =
new MainnetTransactionValidator(
Expand All @@ -351,7 +353,8 @@ public void shouldAcceptOnlyTransactionsInAcceptedTransactionTypes() {
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);

final Transaction transaction =
new TransactionTestFixture()
Expand Down Expand Up @@ -383,7 +386,8 @@ public void shouldRejectTransactionIfEIP1559TransactionGasPriceLessBaseFee() {
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);
final Transaction transaction =
new TransactionTestFixture()
.type(TransactionType.EIP1559)
Expand All @@ -406,7 +410,8 @@ public void shouldAcceptZeroGasPriceTransactionIfBaseFeeIsZero() {
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);
final Transaction transaction =
new TransactionTestFixture()
.type(TransactionType.EIP1559)
Expand All @@ -428,7 +433,8 @@ public void shouldAcceptValidEIP1559() {
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);
final Transaction transaction =
new TransactionTestFixture()
.maxPriorityFeePerGas(Optional.of(Wei.of(1)))
Expand All @@ -452,7 +458,8 @@ public void shouldValidate1559TransactionWithPriceLowerThanBaseFeeForTransaction
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
defaultGoQuorumCompatibilityMode);
defaultGoQuorumCompatibilityMode,
Integer.MAX_VALUE);
final Transaction transaction =
new TransactionTestFixture()
.maxPriorityFeePerGas(Optional.of(Wei.of(1)))
Expand All @@ -468,6 +475,33 @@ public void shouldValidate1559TransactionWithPriceLowerThanBaseFeeForTransaction
.isEqualTo(ValidationResult.valid());
}

@Test
public void shouldRejectTooLargeInitcode() {
final MainnetTransactionValidator validator =
new MainnetTransactionValidator(
gasCalculator,
FeeMarket.london(0L),
false,
Optional.of(BigInteger.ONE),
Set.of(TransactionType.FRONTIER, TransactionType.EIP1559),
defaultGoQuorumCompatibilityMode,
0xc000);

var bigPayload =
new TransactionTestFixture()
.payload(Bytes.fromHexString("0x" + "00".repeat(0xc001)))
.chainId(Optional.of(BigInteger.ONE))
.createTransaction(senderKeys);
var validationResult =
validator.validate(bigPayload, Optional.empty(), transactionValidationParams);

assertThat(validationResult.isValid()).isFalse();
assertThat(validationResult.getInvalidReason())
.isEqualTo(TransactionInvalidReason.INITCODE_TOO_LARGE);
assertThat(validationResult.getErrorMessage())
.isEqualTo("Initcode size of 49153 exceeds maximum size of 49152");
}

@Test
public void goQuorumCompatibilityModeRejectNonZeroGasPrice() {
final MainnetTransactionValidator validator =
Expand Down
Loading

0 comments on commit 901573c

Please sign in to comment.