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

CREATE/deployment transaction different behaviours wrt triggering INVALID_CODE_PREFIX and MAX_CODE_SIZE exceptions #1460

Open
lorenzogentile404 opened this issue Oct 28, 2024 · 3 comments
Assignees

Comments

@lorenzogentile404
Copy link
Collaborator

lorenzogentile404 commented Oct 28, 2024

In this testing class we deliberately try to trigger the INVALID_CODE_PREFIX and MAX_CODE_SIZE. The first two tests of the class try to achieve it by executing a deployment transaction with a payload that returns a portion of memory starting with EIP_3541_MARKER or greater than MAX_CODE_SIZE respectively. The last two, achieves the same result by using CREATE instead of a deployment transaction.
What we observe is that, while the last two tests correctly trigger the expected exceptions, the first two encounter a Java exceptions that seems to be related to Besu. Below the exceptions we encounter:

First test:

11:37:16.993 [Test worker] DEBUG - Transaction 0xf9f77d7caa32abd068a5b173d70723a9590d1ddaae859689a840875676eb54bd processing halted: INVALID_CODE

Transaction: 0xf9f77d7caa32abd068a5b173d70723a9590d1ddaae859689a840875676eb54bd not successful. TransactionProcessingResult{status=FAILED, estimateGasUsedByTransaction=16777215, gasRemaining=0, logs=[], output=0x, validationResult=ValidationResult{invalidReason=Optional[EXECUTION_HALTED], errorMessage=Optional[INVALID_CODE]}, revertReason=Optional.empty}
Expected :true
Actual   :false
<Click to see difference>

org.opentest4j.AssertionFailedError: Transaction: 0xf9f77d7caa32abd068a5b173d70723a9590d1ddaae859689a840875676eb54bd not successful. TransactionProcessingResult{status=FAILED, estimateGasUsedByTransaction=16777215, gasRemaining=0, logs=[], output=0x, validationResult=ValidationResult{invalidReason=Optional[EXECUTION_HALTED], errorMessage=Optional[INVALID_CODE]}, revertReason=Optional.empty} ==> expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:42)
	at org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:191)
	at net.consensys.linea.testing.TransactionProcessingResultValidator.lambda$static$1(TransactionProcessingResultValidator.java:30)
	at net.consensys.linea.testing.GeneralStateReferenceTestTools.executeTest(GeneralStateReferenceTestTools.java:127)
	at net.consensys.linea.testing.ToyExecutionEnvironmentV2.run(ToyExecutionEnvironmentV2.java:69)
	at net.consensys.linea.zktracer.exceptions.InvalidCodePrefixAndMaxCodeSizeExceptionTest.invalidCodePrefixExceptionForDeploymentTransactionTest(InvalidCodePrefixAndMaxCodeSizeExceptionTest.java:81)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:766)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$8(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)

Second test:

11:37:16.936 [Test worker] DEBUG - Transaction 0xce760004f5dfbd94178e8c49d9b010e6c1cecfe896fb98e71431854544c62c9b processing halted: CODE_TOO_LARGE

Transaction: 0xce760004f5dfbd94178e8c49d9b010e6c1cecfe896fb98e71431854544c62c9b not successful. TransactionProcessingResult{status=FAILED, estimateGasUsedByTransaction=16777215, gasRemaining=0, logs=[], output=0x, validationResult=ValidationResult{invalidReason=Optional[EXECUTION_HALTED], errorMessage=Optional[CODE_TOO_LARGE]}, revertReason=Optional.empty}
Expected :true
Actual   :false
<Click to see difference>

org.opentest4j.AssertionFailedError: Transaction: 0xce760004f5dfbd94178e8c49d9b010e6c1cecfe896fb98e71431854544c62c9b not successful. TransactionProcessingResult{status=FAILED, estimateGasUsedByTransaction=16777215, gasRemaining=0, logs=[], output=0x, validationResult=ValidationResult{invalidReason=Optional[EXECUTION_HALTED], errorMessage=Optional[CODE_TOO_LARGE]}, revertReason=Optional.empty} ==> expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:42)
	at org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:191)
	at net.consensys.linea.testing.TransactionProcessingResultValidator.lambda$static$1(TransactionProcessingResultValidator.java:30)
	at net.consensys.linea.testing.GeneralStateReferenceTestTools.executeTest(GeneralStateReferenceTestTools.java:127)
	at net.consensys.linea.testing.ToyExecutionEnvironmentV2.run(ToyExecutionEnvironmentV2.java:69)
	at net.consensys.linea.zktracer.exceptions.InvalidCodePrefixAndMaxCodeSizeExceptionTest.maxCodeSizeExceptionForDeploymentTransactionTest(InvalidCodePrefixAndMaxCodeSizeExceptionTest.java:118)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:766)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$8(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)

@Gabriel-Trintinalia suggested this:

I believe it happens because of the ContractCreationValidation rules. In here -> ExecutionEnvironment class, in the getProtocolSpec try adding

.contractCreationProcessorBuilder(
    evm ->
        new ContractCreationProcessor(
            evm,
            true,
            List.of(),
            1,
            Set.of(Address.fromHexString("0x0000000000000000000000000000000000000003"))))
@Gabriel-Trintinalia
Copy link
Contributor

@lorenzogentile404, is it working as expected with the code snipped above? Can we close this issue?

@lorenzogentile404
Copy link
Collaborator Author

lorenzogentile404 commented Oct 30, 2024

As discussed in our call, while the tests are passing with this patch (and also if we provide an empty set of addresses), the patch leads to a bug in the tracer where Besu says transactions are successful while we expect them to fail in the two tests using a deployment transaction @Gabriel-Trintinalia @OlivierBBB

@OlivierBBB
Copy link
Collaborator

This patch basically disables some exception from the EVM-London (invalidCodePrefixException and maxCodeSizeException, both related to RETURN in deployment contexts) and cannot be integrated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants