Refactor max code size (#7523)

* Refactor max code size

Refactor the max code size to no longer be a part of the operation but
instead is queried from the EVM version specification.

Signed-off-by: Danno Ferrin <danno@numisight.com>

---------

Signed-off-by: Danno Ferrin <danno@numisight.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/7537/head
Danno Ferrin 3 months ago committed by GitHub
parent 5eb670085a
commit 078523df64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      evm/src/main/java/org/hyperledger/besu/evm/ClassicEVMs.java
  2. 12
      evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java
  3. 8
      evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java
  4. 5
      evm/src/main/java/org/hyperledger/besu/evm/operation/Create2Operation.java
  5. 5
      evm/src/main/java/org/hyperledger/besu/evm/operation/CreateOperation.java
  6. 2
      evm/src/main/java/org/hyperledger/besu/evm/operation/EOFCreateOperation.java
  7. 7
      evm/src/test/java/org/hyperledger/besu/evm/operation/AbstractCreateOperationTest.java
  8. 10
      evm/src/test/java/org/hyperledger/besu/evm/operation/Create2OperationTest.java
  9. 17
      evm/src/test/java/org/hyperledger/besu/evm/operation/CreateOperationTest.java

@ -14,13 +14,10 @@
*/ */
package org.hyperledger.besu.evm; package org.hyperledger.besu.evm;
import static org.hyperledger.besu.evm.MainnetEVMs.SHANGHAI_INIT_CODE_SIZE_LIMIT;
import static org.hyperledger.besu.evm.MainnetEVMs.registerIstanbulOperations; import static org.hyperledger.besu.evm.MainnetEVMs.registerIstanbulOperations;
import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.operation.Create2Operation;
import org.hyperledger.besu.evm.operation.CreateOperation;
import org.hyperledger.besu.evm.operation.OperationRegistry; import org.hyperledger.besu.evm.operation.OperationRegistry;
import org.hyperledger.besu.evm.operation.Push0Operation; import org.hyperledger.besu.evm.operation.Push0Operation;
@ -62,8 +59,6 @@ public class ClassicEVMs {
OperationRegistry registry = new OperationRegistry(); OperationRegistry registry = new OperationRegistry();
registerIstanbulOperations(registry, gasCalculator, chainId); registerIstanbulOperations(registry, gasCalculator, chainId);
registry.put(new Push0Operation(gasCalculator)); registry.put(new Push0Operation(gasCalculator));
registry.put(new CreateOperation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
registry.put(new Create2Operation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
return registry; return registry;
} }
} }

@ -147,12 +147,6 @@ public class MainnetEVMs {
/** The constant DEV_NET_CHAIN_ID. */ /** The constant DEV_NET_CHAIN_ID. */
public static final BigInteger DEV_NET_CHAIN_ID = BigInteger.valueOf(1337); public static final BigInteger DEV_NET_CHAIN_ID = BigInteger.valueOf(1337);
/** The constant SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT. */
public static final int SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT = 0x6000;
/** The constant SHANGHAI_INIT_CODE_SIZE_LIMIT. */
public static final int SHANGHAI_INIT_CODE_SIZE_LIMIT = 2 * SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT;
private MainnetEVMs() { private MainnetEVMs() {
// utility class // utility class
} }
@ -264,7 +258,7 @@ public class MainnetEVMs {
registry.put(new InvalidOperation(gasCalculator)); registry.put(new InvalidOperation(gasCalculator));
registry.put(new StopOperation(gasCalculator)); registry.put(new StopOperation(gasCalculator));
registry.put(new SelfDestructOperation(gasCalculator)); registry.put(new SelfDestructOperation(gasCalculator));
registry.put(new CreateOperation(gasCalculator, Integer.MAX_VALUE)); registry.put(new CreateOperation(gasCalculator));
registry.put(new CallOperation(gasCalculator)); registry.put(new CallOperation(gasCalculator));
registry.put(new CallCodeOperation(gasCalculator)); registry.put(new CallCodeOperation(gasCalculator));
@ -474,7 +468,7 @@ public class MainnetEVMs {
public static void registerConstantinopleOperations( public static void registerConstantinopleOperations(
final OperationRegistry registry, final GasCalculator gasCalculator) { final OperationRegistry registry, final GasCalculator gasCalculator) {
registerByzantiumOperations(registry, gasCalculator); registerByzantiumOperations(registry, gasCalculator);
registry.put(new Create2Operation(gasCalculator, Integer.MAX_VALUE)); registry.put(new Create2Operation(gasCalculator));
registry.put(new SarOperation(gasCalculator)); registry.put(new SarOperation(gasCalculator));
registry.put(new ShlOperation(gasCalculator)); registry.put(new ShlOperation(gasCalculator));
registry.put(new ShrOperation(gasCalculator)); registry.put(new ShrOperation(gasCalculator));
@ -809,8 +803,6 @@ public class MainnetEVMs {
final BigInteger chainID) { final BigInteger chainID) {
registerParisOperations(registry, gasCalculator, chainID); registerParisOperations(registry, gasCalculator, chainID);
registry.put(new Push0Operation(gasCalculator)); registry.put(new Push0Operation(gasCalculator));
registry.put(new CreateOperation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
registry.put(new Create2Operation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
} }
/** /**

@ -45,9 +45,6 @@ public abstract class AbstractCreateOperation extends AbstractOperation {
protected static final OperationResult INVALID_OPERATION = protected static final OperationResult INVALID_OPERATION =
new OperationResult(0L, ExceptionalHaltReason.INVALID_OPERATION); new OperationResult(0L, ExceptionalHaltReason.INVALID_OPERATION);
/** The maximum init code size */
protected final int maxInitcodeSize;
/** The EOF Version this create operation requires initcode to be in */ /** The EOF Version this create operation requires initcode to be in */
protected final int eofVersion; protected final int eofVersion;
@ -59,7 +56,6 @@ public abstract class AbstractCreateOperation extends AbstractOperation {
* @param stackItemsConsumed the stack items consumed * @param stackItemsConsumed the stack items consumed
* @param stackItemsProduced the stack items produced * @param stackItemsProduced the stack items produced
* @param gasCalculator the gas calculator * @param gasCalculator the gas calculator
* @param maxInitcodeSize Maximum init code size
* @param eofVersion the EOF version this create operation is valid in * @param eofVersion the EOF version this create operation is valid in
*/ */
protected AbstractCreateOperation( protected AbstractCreateOperation(
@ -68,10 +64,8 @@ public abstract class AbstractCreateOperation extends AbstractOperation {
final int stackItemsConsumed, final int stackItemsConsumed,
final int stackItemsProduced, final int stackItemsProduced,
final GasCalculator gasCalculator, final GasCalculator gasCalculator,
final int maxInitcodeSize,
final int eofVersion) { final int eofVersion) {
super(opcode, name, stackItemsConsumed, stackItemsProduced, gasCalculator); super(opcode, name, stackItemsConsumed, stackItemsProduced, gasCalculator);
this.maxInitcodeSize = maxInitcodeSize;
this.eofVersion = eofVersion; this.eofVersion = eofVersion;
} }
@ -103,7 +97,7 @@ public abstract class AbstractCreateOperation extends AbstractOperation {
Code code = codeSupplier.get(); Code code = codeSupplier.get();
if (code != null && code.getSize() > maxInitcodeSize) { if (code != null && code.getSize() > evm.getEvmVersion().getMaxInitcodeSize()) {
frame.popStackItems(getStackItemsConsumed()); frame.popStackItems(getStackItemsConsumed());
return new OperationResult(cost, ExceptionalHaltReason.CODE_TOO_LARGE); return new OperationResult(cost, ExceptionalHaltReason.CODE_TOO_LARGE);
} }

@ -39,10 +39,9 @@ public class Create2Operation extends AbstractCreateOperation {
* Instantiates a new Create2 operation. * Instantiates a new Create2 operation.
* *
* @param gasCalculator the gas calculator * @param gasCalculator the gas calculator
* @param maxInitcodeSize Maximum init code size
*/ */
public Create2Operation(final GasCalculator gasCalculator, final int maxInitcodeSize) { public Create2Operation(final GasCalculator gasCalculator) {
super(0xF5, "CREATE2", 4, 1, gasCalculator, maxInitcodeSize, 0); super(0xF5, "CREATE2", 4, 1, gasCalculator, 0);
} }
@Override @Override

@ -36,10 +36,9 @@ public class CreateOperation extends AbstractCreateOperation {
* Instantiates a new Create operation. * Instantiates a new Create operation.
* *
* @param gasCalculator the gas calculator * @param gasCalculator the gas calculator
* @param maxInitcodeSize Maximum init code size
*/ */
public CreateOperation(final GasCalculator gasCalculator, final int maxInitcodeSize) { public CreateOperation(final GasCalculator gasCalculator) {
super(0xF0, "CREATE", 3, 1, gasCalculator, maxInitcodeSize, 0); super(0xF0, "CREATE", 3, 1, gasCalculator, 0);
} }
@Override @Override

@ -44,7 +44,7 @@ public class EOFCreateOperation extends AbstractCreateOperation {
* @param gasCalculator the gas calculator * @param gasCalculator the gas calculator
*/ */
public EOFCreateOperation(final GasCalculator gasCalculator) { public EOFCreateOperation(final GasCalculator gasCalculator) {
super(OPCODE, "EOFCREATE", 4, 1, gasCalculator, Integer.MAX_VALUE, 1); super(OPCODE, "EOFCREATE", 4, 1, gasCalculator, 1);
} }
@Override @Override

@ -57,7 +57,7 @@ class AbstractCreateOperationTest {
private final MutableAccount account = mock(MutableAccount.class); private final MutableAccount account = mock(MutableAccount.class);
private final MutableAccount newAccount = mock(MutableAccount.class); private final MutableAccount newAccount = mock(MutableAccount.class);
private final FakeCreateOperation operation = private final FakeCreateOperation operation =
new FakeCreateOperation(new ConstantinopleGasCalculator(), Integer.MAX_VALUE); new FakeCreateOperation(new ConstantinopleGasCalculator());
private static final Bytes SIMPLE_CREATE = private static final Bytes SIMPLE_CREATE =
Bytes.fromHexString( Bytes.fromHexString(
@ -100,10 +100,9 @@ class AbstractCreateOperationTest {
* Instantiates a new Create operation. * Instantiates a new Create operation.
* *
* @param gasCalculator the gas calculator * @param gasCalculator the gas calculator
* @param maxInitcodeSize Maximum init code size
*/ */
public FakeCreateOperation(final GasCalculator gasCalculator, final int maxInitcodeSize) { public FakeCreateOperation(final GasCalculator gasCalculator) {
super(0xEF, "FAKECREATE", 3, 1, gasCalculator, maxInitcodeSize, 0); super(0xEF, "FAKECREATE", 3, 1, gasCalculator, 0);
} }
@Override @Override

@ -60,11 +60,7 @@ public class Create2OperationTest {
private final MutableAccount newAccount = mock(MutableAccount.class); private final MutableAccount newAccount = mock(MutableAccount.class);
private final Create2Operation operation = private final Create2Operation operation =
new Create2Operation(new ConstantinopleGasCalculator(), Integer.MAX_VALUE); new Create2Operation(new ConstantinopleGasCalculator());
private final Create2Operation maxInitCodeOperation =
new Create2Operation(
new ConstantinopleGasCalculator(), MainnetEVMs.SHANGHAI_INIT_CODE_SIZE_LIMIT);
private static final String TOPIC = private static final String TOPIC =
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // 32 FFs "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // 32 FFs
@ -221,7 +217,7 @@ public class Create2OperationTest {
when(worldUpdater.updater()).thenReturn(worldUpdater); when(worldUpdater.updater()).thenReturn(worldUpdater);
final EVM myEVM = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT); final EVM myEVM = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT);
var result = maxInitCodeOperation.execute(messageFrame, myEVM); var result = operation.execute(messageFrame, myEVM);
final MessageFrame createFrame = messageFrame.getMessageFrameStack().peek(); final MessageFrame createFrame = messageFrame.getMessageFrameStack().peek();
final ContractCreationProcessor ccp = final ContractCreationProcessor ccp =
new ContractCreationProcessor(myEVM, false, List.of(), 0, List.of()); new ContractCreationProcessor(myEVM, false, List.of(), 0, List.of());
@ -250,7 +246,7 @@ public class Create2OperationTest {
when(worldUpdater.updater()).thenReturn(worldUpdater); when(worldUpdater.updater()).thenReturn(worldUpdater);
final EVM evm = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT); final EVM evm = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT);
var result = maxInitCodeOperation.execute(messageFrame, evm); var result = operation.execute(messageFrame, evm);
assertThat(result.getHaltReason()).isEqualTo(CODE_TOO_LARGE); assertThat(result.getHaltReason()).isEqualTo(CODE_TOO_LARGE);
} }

@ -52,12 +52,7 @@ class CreateOperationTest {
private final WorldUpdater worldUpdater = mock(WorldUpdater.class); private final WorldUpdater worldUpdater = mock(WorldUpdater.class);
private final MutableAccount account = mock(MutableAccount.class); private final MutableAccount account = mock(MutableAccount.class);
private final MutableAccount newAccount = mock(MutableAccount.class); private final MutableAccount newAccount = mock(MutableAccount.class);
private final CreateOperation operation = private final CreateOperation operation = new CreateOperation(new ConstantinopleGasCalculator());
new CreateOperation(new ConstantinopleGasCalculator(), Integer.MAX_VALUE);
private final CreateOperation maxInitCodeOperation =
new CreateOperation(
new ConstantinopleGasCalculator(), MainnetEVMs.SHANGHAI_INIT_CODE_SIZE_LIMIT);
private final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
private static final String TOPIC = private static final String TOPIC =
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // 32 FFs "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // 32 FFs
@ -82,7 +77,7 @@ class CreateOperationTest {
@Test @Test
void createFromMemoryMutationSafe() { void createFromMemoryMutationSafe() {
// Given: Execute a CREATE operation with a contract that logs in the constructor // Given: Execute a CREATE operation with a contract that logs in the constructor
final UInt256 memoryOffset = UInt256.fromHexString("0xFF"); final UInt256 memoryOffset = UInt256.fromHexString("0xFF");
final UInt256 memoryLength = UInt256.valueOf(SIMPLE_CREATE.size()); final UInt256 memoryLength = UInt256.valueOf(SIMPLE_CREATE.size());
final MessageFrame messageFrame = testMemoryFrame(memoryOffset, memoryLength, UInt256.ZERO, 1); final MessageFrame messageFrame = testMemoryFrame(memoryOffset, memoryLength, UInt256.ZERO, 1);
@ -190,7 +185,7 @@ class CreateOperationTest {
when(worldUpdater.updater()).thenReturn(worldUpdater); when(worldUpdater.updater()).thenReturn(worldUpdater);
final EVM evm = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT); final EVM evm = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT);
var result = maxInitCodeOperation.execute(messageFrame, evm); var result = operation.execute(messageFrame, evm);
final MessageFrame createFrame = messageFrame.getMessageFrameStack().peek(); final MessageFrame createFrame = messageFrame.getMessageFrameStack().peek();
final ContractCreationProcessor ccp = final ContractCreationProcessor ccp =
new ContractCreationProcessor(evm, false, List.of(), 0, List.of()); new ContractCreationProcessor(evm, false, List.of(), 0, List.of());
@ -218,17 +213,18 @@ class CreateOperationTest {
when(worldUpdater.updater()).thenReturn(worldUpdater); when(worldUpdater.updater()).thenReturn(worldUpdater);
final EVM evm = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT); final EVM evm = MainnetEVMs.shanghai(DEV_NET_CHAIN_ID, EvmConfiguration.DEFAULT);
var result = maxInitCodeOperation.execute(messageFrame, evm); var result = operation.execute(messageFrame, evm);
assertThat(result.getHaltReason()).isEqualTo(CODE_TOO_LARGE); assertThat(result.getHaltReason()).isEqualTo(CODE_TOO_LARGE);
} }
@Test @Test
void eofV1CannotCall() { void eofV1CannotCall() {
final EVM pragueEvm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
final UInt256 memoryOffset = UInt256.fromHexString("0xFF"); final UInt256 memoryOffset = UInt256.fromHexString("0xFF");
final UInt256 memoryLength = UInt256.valueOf(SIMPLE_CREATE.size()); final UInt256 memoryLength = UInt256.valueOf(SIMPLE_CREATE.size());
final MessageFrame messageFrame = final MessageFrame messageFrame =
new TestMessageFrameBuilder() new TestMessageFrameBuilder()
.code(evm.getCodeUncached(SIMPLE_EOF)) .code(pragueEvm.getCodeUncached(SIMPLE_EOF))
.pushStackItem(memoryLength) .pushStackItem(memoryLength)
.pushStackItem(memoryOffset) .pushStackItem(memoryOffset)
.pushStackItem(Bytes.EMPTY) .pushStackItem(Bytes.EMPTY)
@ -252,6 +248,7 @@ class CreateOperationTest {
final UInt256 memoryLength, final UInt256 memoryLength,
final UInt256 value, final UInt256 value,
final int depth) { final int depth) {
final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT);
final MessageFrame messageFrame = final MessageFrame messageFrame =
MessageFrame.builder() MessageFrame.builder()
.type(MessageFrame.Type.CONTRACT_CREATION) .type(MessageFrame.Type.CONTRACT_CREATION)

Loading…
Cancel
Save