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

1444 failing tests for testmxprandomadvanced #1448

Open
wants to merge 8 commits into
base: arith-dev
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static net.consensys.linea.zktracer.module.UtilCalculator.allButOneSixtyFourth;
import static net.consensys.linea.zktracer.types.AddressUtils.isPrecompile;

import com.google.common.base.Preconditions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.consensys.linea.zktracer.module.constants.GlobalConstants;
Expand Down Expand Up @@ -164,14 +165,36 @@ public static Bytes initCode(final MessageFrame frame) {
public static MemorySpan returnDataRequestedSegment(final MessageFrame frame) {
switch (OpCode.of(frame.getCurrentOperation().getOpcode())) {
case CALL, CALLCODE -> {
long offset = Words.clampedToLong(frame.getStackItem(5));
long length = Words.clampedToLong(frame.getStackItem(6));
return MemorySpan.fromStartLength(offset, length);
long callDataOffset = Words.clampedToLong(frame.getStackItem(3));
long callDataSize = Words.clampedToLong(frame.getStackItem(4));
long returnDataOffset = Words.clampedToLong(frame.getStackItem(5));
long returnDataSize = Words.clampedToLong(frame.getStackItem(6));

Preconditions.checkArgument(!(callDataOffset >= Math.pow(2, 32) && callDataSize == 0));
Preconditions.checkArgument(!(returnDataOffset >= Math.pow(2, 32) && returnDataSize == 0));

System.out.println("callDataOffset: " + callDataOffset);
System.out.println("callDataSize: " + callDataSize);
System.out.println("returnDataOffset: " + returnDataOffset);
System.out.println("returnDataSize: " + returnDataSize);

return MemorySpan.fromStartLength(returnDataOffset, returnDataSize);
}
case DELEGATECALL, STATICCALL -> {
long offset = Words.clampedToLong(frame.getStackItem(4));
long length = Words.clampedToLong(frame.getStackItem(5));
return MemorySpan.fromStartLength(offset, length);
long callDataOffset = Words.clampedToLong(frame.getStackItem(2));
long callDataSize = Words.clampedToLong(frame.getStackItem(3));
long returnDataOffset = Words.clampedToLong(frame.getStackItem(4));
long returnDataSize = Words.clampedToLong(frame.getStackItem(5));

System.out.println("callDataOffset: " + callDataOffset);
System.out.println("callDataSize: " + callDataSize);
System.out.println("returnDataOffset: " + returnDataOffset);
System.out.println("returnDataSize: " + returnDataSize);

Preconditions.checkArgument(!(callDataOffset >= Math.pow(2, 32) && callDataSize == 0));
Preconditions.checkArgument(!(returnDataOffset >= Math.pow(2, 32) && returnDataSize == 0));

return MemorySpan.fromStartLength(returnDataOffset, returnDataSize);
}
default -> throw new IllegalArgumentException(
"returnDataRequestedSegment called outside of a *CALL");
Expand Down Expand Up @@ -221,7 +244,7 @@ public static MemorySpan outputDataSpan(final MessageFrame frame) {
// We cannot use this method for that purpose.
case CALL, CALLCODE, DELEGATECALL, STATICCALL -> {
Address target = Words.toAddress(frame.getStackItem(1));
if (isPrecompile(target)) {
if (!isPrecompile(target)) {
return MemorySpan.fromStartLength(0, 0);
}
checkArgument(isPrecompile(target)); // useless (?) sanity check
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright ConsenSys Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

package net.consensys.linea.zktracer.module.hub;

import java.util.List;

import net.consensys.linea.testing.BytecodeCompiler;
import net.consensys.linea.testing.BytecodeRunner;
import net.consensys.linea.testing.ToyAccount;
import net.consensys.linea.zktracer.opcode.OpCode;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.junit.jupiter.api.Test;

public class ZeroSizeCallDataOrReturnDataTest {

@Test
void zeroSizeHugeReturnAtOffsetTest() {
BytecodeCompiler program = BytecodeCompiler.newProgram();
program
.push(0) // return data size
.push("ff".repeat(32)) // return data offset
.push(0) // call data size
.push(0) // call data offset
.push("ca11ee") // address
.push(1000) // gas
.op(OpCode.STATICCALL);

BytecodeCompiler calleeProgram = BytecodeCompiler.newProgram();
calleeProgram.op(OpCode.CALLDATASIZE);

final ToyAccount calleeAccount =
ToyAccount.builder()
.balance(Wei.fromEth(1))
.nonce(10)
.address(Address.fromHexString("ca11ee"))
.code(calleeProgram.compile())
.build();

BytecodeRunner.of(program.compile()).run(Wei.fromEth(1), 30000L, List.of(calleeAccount));
// TODO: this test is supposed to fail as the ones below, but it does not. Understand why
}

@Test
void zeroSizeHugeCallDataOffsetTest() {
BytecodeCompiler program = BytecodeCompiler.newProgram();
program
.push(0) // return data size
.push(0) // return data offset
.push(0) // call data size
.push("ff".repeat(32)) // call data offset
.push("ca11ee") // address
.push(1000) // gas
.op(OpCode.STATICCALL);

BytecodeCompiler calleeProgram = BytecodeCompiler.newProgram();
calleeProgram.op(OpCode.CALLDATASIZE);

final ToyAccount calleeAccount =
ToyAccount.builder()
.balance(Wei.fromEth(1))
.nonce(10)
.address(Address.fromHexString("ca11ee"))
.code(calleeProgram.compile())
.build();

BytecodeRunner.of(program.compile()).run(Wei.fromEth(1), 30000L, List.of(calleeAccount));
}

@Test
void zeroSizeHugeReturnDataOffsetTest() {
BytecodeCompiler program = BytecodeCompiler.newProgram();
program
.push(0) // return data size
.push(0) // return data offset
.push(0) // call data size
.push(0) // call data offset
.push("ca11ee") // address
.push(1000) // gas
.op(OpCode.STATICCALL);

BytecodeCompiler calleeProgram = BytecodeCompiler.newProgram();
calleeProgram.push(0).push("ff".repeat(32)).op(OpCode.RETURN);

final ToyAccount calleeAccount =
ToyAccount.builder()
.balance(Wei.fromEth(1))
.nonce(10)
.address(Address.fromHexString("ca11ee"))
.code(calleeProgram.compile())
.build();

BytecodeRunner.of(program.compile()).run(Wei.fromEth(1), 30000L, List.of(calleeAccount));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

// https://github.com/Consensys/linea-besu-plugin/issues/197

@Execution(ExecutionMode.SAME_THREAD)
public class MxpTest {
private static final Random RAND = new Random(123456789123456L);
private Random RAND;
public static final EWord TWO_POW_128 = EWord.of(EWord.ONE.shiftLeft(128));
public static final EWord TWO_POW_32 = EWord.of(EWord.ONE.shiftLeft(32));

Expand All @@ -74,6 +78,13 @@ public class MxpTest {

final OpCode[] opCodesHalting = new OpCode[] {OpCode.RETURN, OpCode.REVERT};

@BeforeEach
void init() {
// The random generator is re-initialized before each test so to do not make them
// order-dependent
RAND = new Random(123456789123456L);
}

@Test
void testMxpMinimalNonEmptyReturn() {
BytecodeRunner.of(Bytes.fromHexString("6101006000f3")).run();
Expand Down Expand Up @@ -181,18 +192,42 @@ void testMxpxOrRoob() {

@Test
void testMxpRandomAdvanced() {
// Testing a random program that contains creates with meaning random arguments
Bytes INIT = getRandomINITForCreate(); // This is the value given as an argument to CREATE
// Testing a random program that contains creates with meaningful random arguments
Bytes INIT = getRandomINITForCreate(256); // This is the value given as an argument to CREATE

BytecodeCompiler program = BytecodeCompiler.newProgram();
int instructionCount = 256;
for (int i = 0; i < instructionCount; i++) {
boolean isHalting = i == instructionCount - 1;
int INSTRUCTION_COUNT = 256;
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
boolean isHalting = i == INSTRUCTION_COUNT - 1;
triggerNonTrivialOrNoop(program, isHalting, INIT);
}
BytecodeRunner.of(program.compile()).run();
}

@ParameterizedTest
@MethodSource("testMxpRandomAdvancedSource")
void testMxpRandomAdvancedWithFixedSeed(
long SEED, int INSTRUCTION_COUNT_INIT, int INSTRUCTION_COUNT) {
// Overwrite the class-level random generator with a new one with a fixed seed
RAND = new Random(SEED);
// Testing a random program that contains creates with meaningful random arguments
Bytes INIT =
getRandomINITForCreate(
INSTRUCTION_COUNT_INIT); // This is the value given as an argument to CREATE

BytecodeCompiler program = BytecodeCompiler.newProgram();
for (int i = 0; i < INSTRUCTION_COUNT; i++) {
boolean isHalting = i == INSTRUCTION_COUNT - 1;
triggerNonTrivialOrNoop(program, isHalting, INIT);
}
BytecodeRunner.of(program.compile()).run();
}

private static Stream<Arguments> testMxpRandomAdvancedSource() {
// Failing test cases
return Stream.of(Arguments.of(166L, 3, 2), Arguments.of(44L, 3, 3), Arguments.of(244L, 5, 5));
}

@Test
void testCall() {
/* NOTE: The contracts in this test are compiled by using
Expand Down Expand Up @@ -302,8 +337,7 @@ void testCall() {
}

// Support methods
private Bytes getRandomINITForCreate() {
final int INSTRUCTION_COUNT_INIT = 256;
private Bytes getRandomINITForCreate(final int INSTRUCTION_COUNT_INIT) {
BytecodeCompiler INIT = BytecodeCompiler.newProgram();
for (int i = 0; i < INSTRUCTION_COUNT_INIT; i++) {
boolean isHalting = i == INSTRUCTION_COUNT_INIT - 1;
Expand Down Expand Up @@ -385,6 +419,8 @@ private void triggerNonTrivialOrNoop(BytecodeCompiler program, boolean isHalting
appendOpCodeCall(List.of(value, offset1), opCode, program);
break;
case LOG0, SHA3, RETURN, REVERT: // RETURN and REVERT are selected only when isHalting is true
System.out.println(
opCode + " size: " + size1.toBigInteger() + " offset: " + offset1.toBigInteger());
appendOpCodeCall(List.of(size1, offset1), opCode, program);
if (opCode == OpCode.SHA3) {
program.op(OpCode.POP);
Expand Down Expand Up @@ -548,9 +584,7 @@ private void triggerNonTrivialButMxpxOrRoob(
}

private boolean isRoob(MxpType randomMxpType, EWord size1, EWord offset1) {

final boolean condition4And5 = offset1.compareTo(TWO_POW_128) >= 0 && !size1.isZero();

return switch (randomMxpType) {
case TYPE_2, TYPE_3 -> offset1.compareTo(TWO_POW_128) >= 0;
case TYPE_4 -> size1.compareTo(TWO_POW_128) >= 0 || condition4And5;
Expand Down
Loading