Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* 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.blockdata;

import static net.consensys.linea.zktracer.Trace.*;
import static net.consensys.linea.zktracer.types.Conversions.ZERO;
import static net.consensys.linea.zktracer.types.Conversions.booleanToBytes;

import lombok.Builder;
import lombok.Getter;
import lombok.experimental.Accessors;
import net.consensys.linea.zktracer.module.euc.Euc;
import net.consensys.linea.zktracer.module.euc.EucOperation;
import net.consensys.linea.zktracer.module.wcp.Wcp;
import net.consensys.linea.zktracer.types.EWord;
import org.apache.tuweni.bytes.Bytes;

@Builder
@Getter
@Accessors(fluent = true)
public class BlockDataExoCall {

@Builder.Default private final boolean wcpFlag = false;
@Builder.Default private final boolean eucFlag = false;
@Builder.Default private final int instruction = 0;
@Builder.Default private final Bytes arg1Hi = Bytes.EMPTY;
@Builder.Default private final Bytes arg1Lo = Bytes.EMPTY;
@Builder.Default private final Bytes arg2Hi = Bytes.EMPTY;
@Builder.Default private final Bytes arg2Lo = Bytes.EMPTY;
// Results for wcp computations
// Quotients for euc computations in trace
@Builder.Default private final Bytes res = ZERO;

public static BlockDataExoCall callToLT(final Wcp wcp, Bytes arg1, Bytes arg2) {

final EWord arg1B32 = EWord.of(arg1);
final EWord arg2B32 = EWord.of(arg2);

return BlockDataExoCall.builder()
.wcpFlag(true)
.instruction(EVM_INST_LT)
.arg1Hi(arg1B32.lo())
.arg1Lo(arg1B32.hi())
.arg2Hi(arg2B32.lo())
.arg2Lo(arg2B32.hi())
.res(booleanToBytes(wcp.callLT(arg1B32, arg2B32)))
.build();
}

public static BlockDataExoCall callToGT(final Wcp wcp, Bytes arg1, Bytes arg2) {

final EWord arg1B32 = EWord.of(arg1);
final EWord arg2B32 = EWord.of(arg2);

return BlockDataExoCall.builder()
.wcpFlag(true)
.instruction(EVM_INST_GT)
.arg1Hi(arg1B32.lo())
.arg1Lo(arg1B32.hi())
.arg2Hi(arg2B32.lo())
.arg2Lo(arg2B32.hi())
.res(booleanToBytes(wcp.callLT(arg1B32, arg2B32)))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Comparison Methods Return Incorrect Values

The callToGT method calls wcp.callLT instead of wcp.callGT, and callToGEQ calls wcp.callLEQ instead of wcp.callGEQ. This copy-paste error results in both methods returning the opposite boolean value for their intended comparisons.

Additional Locations (1)

Fix in Cursor Fix in Web

.build();
}

public static BlockDataExoCall callToLEQ(final Wcp wcp, Bytes arg1, Bytes arg2) {

final EWord arg1B32 = EWord.of(arg1);
final EWord arg2B32 = EWord.of(arg2);

return BlockDataExoCall.builder()
.wcpFlag(true)
.instruction(WCP_INST_LEQ)
.arg1Hi(arg1B32.lo())
.arg1Lo(arg1B32.hi())
.arg2Hi(arg2B32.lo())
.arg2Lo(arg2B32.hi())
.res(booleanToBytes(wcp.callLEQ(arg1B32, arg2B32)))
.build();
}

public static BlockDataExoCall callToGEQ(final Wcp wcp, Bytes arg1, Bytes arg2) {

final EWord arg1B32 = EWord.of(arg1);
final EWord arg2B32 = EWord.of(arg2);

return BlockDataExoCall.builder()
.wcpFlag(true)
.instruction(WCP_INST_GEQ)
.arg1Hi(arg1B32.lo())
.arg1Lo(arg1B32.hi())
.arg2Hi(arg2B32.lo())
.arg2Lo(arg2B32.hi())
.res(booleanToBytes(wcp.callLEQ(arg1B32, arg2B32)))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Incorrect Method Call Causes Comparison Error

The callToGEQ method incorrectly calls wcp.callLEQ instead of wcp.callGEQ. This causes it to perform a less-than-or-equal comparison, returning the opposite boolean result for greater-than-or-equal checks.

Fix in Cursor Fix in Web

.build();
}

public static BlockDataExoCall callToIsZero(final Wcp wcp, Bytes arg1) {

final EWord arg1B32 = EWord.of(arg1);

return BlockDataExoCall.builder()
.wcpFlag(true)
.instruction(EVM_INST_ISZERO)
.arg1Hi(arg1B32.slice(0, LLARGE))
.arg1Lo(arg1B32.slice(LLARGE, LLARGE))
.res(booleanToBytes(wcp.callISZERO(arg1B32)))
.build();
}

public static BlockDataExoCall callToEUC(final Euc euc, Bytes arg1, Bytes arg2) {

final EWord arg1B32 = EWord.of(arg1);
final EWord arg2B32 = EWord.of(arg2);

EucOperation eucOperation = euc.callEUC(arg1B32, arg2B32);

return BlockDataExoCall.builder()
.eucFlag(true)
.arg1Lo(arg1B32.hi())
.arg2Lo(arg2B32.hi())
.res(eucOperation.quotient())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,16 @@
import net.consensys.linea.zktracer.Trace;
import net.consensys.linea.zktracer.container.module.Module;
import net.consensys.linea.zktracer.module.ModuleName;
import net.consensys.linea.zktracer.module.blockdata.moduleOperation.BlockdataOperation;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.BaseFeeInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.BlobBaseFeeInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.BlockDataInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.ChainIdInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.CoinbaseInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.DifficultyInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.GasLimitInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.NumberInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.PrevRandaoInstruction;
import net.consensys.linea.zktracer.module.blockdata.moduleInstruction.TimestampInstruction;
import net.consensys.linea.zktracer.module.euc.Euc;
import net.consensys.linea.zktracer.module.hub.Hub;
import net.consensys.linea.zktracer.module.txndata.TxnData;
Expand All @@ -43,12 +52,14 @@ public abstract class Blockdata implements Module {
private final Wcp wcp;
private final Euc euc;
private final ChainConfig chain;
@Getter private final List<BlockdataOperation> operations = new ArrayList<>();
@Getter private long firstBlockNumber;
@Getter public final Map<Long, List<BlockDataInstruction>> blockInstructions = new HashMap<>();
@Getter public long firstBlockNumber;
public long blockTimestamp;
public long blockNumber;

private boolean conflationFinished = false;

@Getter private final OpCode[] opCodes = setOpCodes();
@Getter public final OpCode[] opCodes = setOpCodes();

@Override
public ModuleName moduleKey() {
Expand Down Expand Up @@ -81,39 +92,23 @@ public void traceEndConflation(final WorldView state) {

@Override
public void traceEndBlock(final BlockHeader blockHeader, final BlockBody blockBody) {
final long blockNumber = blockHeader.getNumber();
if (operations.isEmpty()) {
blockNumber = blockHeader.getNumber();
blockTimestamp = blockHeader.getTimestamp();
if (blockInstructions.isEmpty()) {
firstBlockNumber = blockNumber;
}
final BlockHeader previousBlockHeader =
operations.isEmpty() ? null : operations.getLast().blockHeader();
final BlockHeader previousBlockHeader = null;
// instructions.isEmpty() ? null : instructions.getLast().blockHeader();
List<BlockDataInstruction> blockDataInstructionList = new ArrayList<>();
for (OpCode opCode : opCodes) {
final BlockdataOperation operation =
setBlockDataOperation(
hub,
blockHeader,
previousBlockHeader,
txnData().numberOfUserTransactionsInCurrentBlock(),
wcp,
euc,
chain,
opCode,
firstBlockNumber);
operations.addLast(operation);
BlockDataInstruction blockDataInstruction =
getInstruction(opCode, blockHeader, previousBlockHeader);
blockDataInstruction.handle();
blockDataInstructionList.addLast(blockDataInstruction);
}
blockInstructions.put(blockNumber - firstBlockNumber, blockDataInstructionList);
}

protected abstract BlockdataOperation setBlockDataOperation(
Hub hub,
BlockHeader blockHeader,
BlockHeader previousBlockHeader,
int nbOfTxsInBlock,
Wcp wcp,
Euc euc,
ChainConfig chain,
OpCode opCode,
long firstBlockNumber);

protected abstract OpCode[] setOpCodes();

@Override
Expand All @@ -124,7 +119,7 @@ public void popTransactionBundle() {}

@Override
public int lineCount() {
final int numberOfBlock = (operations.size() / opCodes.length) + (conflationFinished ? 0 : 1);
final int numberOfBlock = blockInstructions.size() + (conflationFinished ? 0 : 1);
return numberOfBlock * numberOfLinesPerBlock();
}

Expand All @@ -140,14 +135,48 @@ public List<Trace.ColumnHeader> columnHeaders(Trace trace) {
return trace.blockdata().headers(this.lineCount());
}

protected abstract void traceTimestampAndNumber(Trace.Blockdata trace);

protected abstract void traceRelTxNumMax(Trace.Blockdata trace, short relTxMax);

@Override
public void commit(Trace trace) {
for (BlockdataOperation blockData : operations) {
blockData.trace(trace.blockdata());

for (Map.Entry<Long, List<BlockDataInstruction>> entry : blockInstructions.entrySet()) {
Long key = entry.getKey();
List<BlockDataInstruction> value = entry.getValue();
for (BlockDataInstruction blockDataInstruction : value) {
blockDataInstruction.trace(trace.blockdata());
}
}
}

TxnData txnData() {
return hub.txnData();
}

public BlockDataInstruction getInstruction(
OpCode opCode, BlockHeader blockHeader, BlockHeader prevBlockHeader) {
return switch (opCode) {
case COINBASE -> new CoinbaseInstruction(
OpCode.COINBASE, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case TIMESTAMP -> new TimestampInstruction(
OpCode.TIMESTAMP, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case NUMBER -> new NumberInstruction(
OpCode.NUMBER, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case DIFFICULTY -> new DifficultyInstruction(
OpCode.DIFFICULTY, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case PREVRANDAO -> new PrevRandaoInstruction(
OpCode.PREVRANDAO, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case GASLIMIT -> new GasLimitInstruction(
OpCode.GASLIMIT, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case CHAINID -> new ChainIdInstruction(
OpCode.CHAINID, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case BASEFEE -> new BaseFeeInstruction(
OpCode.BASEFEE, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
case BLOBBASEFEE -> new BlobBaseFeeInstruction(
OpCode.BLOBBASEFEE, chain, hub, wcp, euc, blockHeader, prevBlockHeader, firstBlockNumber);
default -> throw new IllegalArgumentException("[BlockData] Unsupported opcode " + opCode);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
import static net.consensys.linea.zktracer.opcode.OpCode.PREVRANDAO;

import net.consensys.linea.zktracer.ChainConfig;
import net.consensys.linea.zktracer.module.blockdata.moduleOperation.BlockdataOperation;
import net.consensys.linea.zktracer.module.blockdata.moduleOperation.CancunBlockDataOperation;
import net.consensys.linea.zktracer.Trace;
import net.consensys.linea.zktracer.module.euc.Euc;
import net.consensys.linea.zktracer.module.hub.Hub;
import net.consensys.linea.zktracer.module.wcp.Wcp;
import net.consensys.linea.zktracer.opcode.OpCode;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.apache.tuweni.bytes.Bytes;

public class CancunBlockData extends ShanghaiBlockData {

Expand All @@ -47,30 +46,17 @@ protected OpCode[] setOpCodes() {
}

@Override
protected int numberOfLinesPerBlock() {
return NB_ROWS_BLOCK_DATA;
public void traceTimestampAndNumber(Trace.Blockdata trace) {
trace.timestamp(Bytes.ofUnsignedLong(blockTimestamp)).number(blockNumber);
}

@Override
protected BlockdataOperation setBlockDataOperation(
Hub hub,
BlockHeader blockHeader,
BlockHeader previousBlockHeader,
int nbOfTxsInBlock,
Wcp wcp,
Euc euc,
ChainConfig chain,
OpCode opCode,
long firstBlockNumber) {
return new CancunBlockDataOperation(
hub,
blockHeader,
previousBlockHeader,
txnData().numberOfUserTransactionsInCurrentBlock(),
wcp,
euc,
chain,
opCode,
firstBlockNumber);
protected void traceRelTxNumMax(Trace.Blockdata trace, short relTxMax) {
// Column not in Cancun fork. Only before Cancun.
}

@Override
protected int numberOfLinesPerBlock() {
return NB_ROWS_BLOCK_DATA;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@
import static net.consensys.linea.zktracer.opcode.OpCode.*;

import net.consensys.linea.zktracer.ChainConfig;
import net.consensys.linea.zktracer.module.blockdata.moduleOperation.BlockdataOperation;
import net.consensys.linea.zktracer.module.blockdata.moduleOperation.LondonBlockDataOperation;
import net.consensys.linea.zktracer.Trace;
import net.consensys.linea.zktracer.module.euc.Euc;
import net.consensys.linea.zktracer.module.hub.Hub;
import net.consensys.linea.zktracer.module.wcp.Wcp;
import net.consensys.linea.zktracer.opcode.OpCode;
import org.hyperledger.besu.plugin.data.BlockHeader;

public class LondonBlockData extends Blockdata {

Expand All @@ -39,30 +37,15 @@ protected OpCode[] setOpCodes() {
}

@Override
protected int numberOfLinesPerBlock() {
return nROWS_DEPTH;
protected void traceTimestampAndNumber(Trace.Blockdata trace) {}

@Override
protected void traceRelTxNumMax(Trace.Blockdata trace, short relTxMax) {
trace.relTxNumMax(relTxMax);
}

@Override
protected BlockdataOperation setBlockDataOperation(
Hub hub,
BlockHeader blockHeader,
BlockHeader previousBlockHeader,
int nbOfTxsInBlock,
Wcp wcp,
Euc euc,
ChainConfig chain,
OpCode opCode,
long firstBlockNumber) {
return new LondonBlockDataOperation(
hub,
blockHeader,
previousBlockHeader,
txnData().numberOfUserTransactionsInCurrentBlock(),
wcp,
euc,
chain,
opCode,
firstBlockNumber);
protected int numberOfLinesPerBlock() {
return nROWS_DEPTH;
}
}
Loading
Loading