diff --git a/CHANGELOG.md b/CHANGELOG.md index 722bc4e087..650a5d62ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,8 @@ Testing pre-release from branch test-release/v0.1.4-test2 * revert make loginfo counts closer to Geth * head: disable stp & txndata +======= +>>>>>>> 820918a3 (temp: geth-compatibily hacks) ## 0.1.4-test Temporary line counting release for testnet. diff --git a/acceptance-tests/src/test/resources/moduleLimits.toml b/acceptance-tests/src/test/resources/moduleLimits.toml index 832136d5cf..acbd02bc3e 100644 --- a/acceptance-tests/src/test/resources/moduleLimits.toml +++ b/acceptance-tests/src/test/resources/moduleLimits.toml @@ -26,6 +26,8 @@ MXP = 524288 PHONEY_RLP = 65536 # can probably get lower PUB_HASH = 32768 PUB_HASH_INFO = 8192 +OLD_PUB_HASH = 32768 +OLD_PUB_HASH_INFO = 8192 PUB_LOG = 16384 PUB_LOG_INFO = 16384 RLP = 128 @@ -64,4 +66,13 @@ PRECOMPILE_ECADD_EFFECTIVE_CALL = 10000 PRECOMPILE_ECMUL_EFFECTIVE_CALL = 10000 PRECOMPILE_ECPAIRING_EFFECTIVE_CALL = 10000 PRECOMPILE_ECPAIRING_MILLER_LOOP = 10000 -PRECOMPILE_BLAKE2F_ROUNDS = 512 \ No newline at end of file +PRECOMPILE_BLAKE2F_ROUNDS = 512 + +PRECOMPILE_BLAKE2F = 512 +PRECOMPILE_ECADD = 512 +PRECOMPILE_ECMUL = 512 +PRECOMPILE_ECPAIRING = 512 +PRECOMPILE_ECRECOVER = 512 +PRECOMPILE_MODEXP = 512 +PRECOMPILE_RIPEMD = 512 +PRECOMPILE_SHA2 = 512 \ No newline at end of file diff --git a/acceptance-tests/src/test/resources/noModuleLimits.toml b/acceptance-tests/src/test/resources/noModuleLimits.toml index aafa376166..107e4c5b44 100644 --- a/acceptance-tests/src/test/resources/noModuleLimits.toml +++ b/acceptance-tests/src/test/resources/noModuleLimits.toml @@ -26,6 +26,8 @@ MXP = 524288 PHONEY_RLP = 65536 # can probably get lower PUB_HASH = 32768 PUB_HASH_INFO = 8192 +OLD_PUB_HASH = 32768 +OLD_PUB_HASH_INFO = 8192 PUB_LOG = 16384 PUB_LOG_INFO = 16384 RLP = 128 @@ -64,4 +66,13 @@ PRECOMPILE_ECADD_EFFECTIVE_CALL = 10000 PRECOMPILE_ECMUL_EFFECTIVE_CALL = 10000 PRECOMPILE_ECPAIRING_EFFECTIVE_CALL = 10000 PRECOMPILE_ECPAIRING_MILLER_LOOP = 10000 -PRECOMPILE_BLAKE2F_ROUNDS = 512 \ No newline at end of file +PRECOMPILE_BLAKE2F_ROUNDS = 512 + +PRECOMPILE_BLAKE2F = 512 +PRECOMPILE_ECADD = 512 +PRECOMPILE_ECMUL = 512 +PRECOMPILE_ECPAIRING = 512 +PRECOMPILE_ECRECOVER = 512 +PRECOMPILE_MODEXP = 512 +PRECOMPILE_RIPEMD = 512 +PRECOMPILE_SHA2 = 512 \ No newline at end of file diff --git a/acceptance-tests/src/test/resources/txOverflowModuleLimits.toml b/acceptance-tests/src/test/resources/txOverflowModuleLimits.toml index 60b0948aa1..4a1995194a 100644 --- a/acceptance-tests/src/test/resources/txOverflowModuleLimits.toml +++ b/acceptance-tests/src/test/resources/txOverflowModuleLimits.toml @@ -27,6 +27,8 @@ MXP = 20 PHONEY_RLP = 65536 # can probably get lower PUB_HASH = 32768 PUB_HASH_INFO = 8192 +OLD_PUB_HASH = 32768 +OLD_PUB_HASH_INFO = 8192 PUB_LOG = 16384 PUB_LOG_INFO = 16384 RLP = 128 @@ -65,4 +67,13 @@ PRECOMPILE_ECADD_EFFECTIVE_CALL = 10000 PRECOMPILE_ECMUL_EFFECTIVE_CALL = 10000 PRECOMPILE_ECPAIRING_EFFECTIVE_CALL = 10000 PRECOMPILE_ECPAIRING_MILLER_LOOP = 10000 -PRECOMPILE_BLAKE2F_ROUNDS = 512 \ No newline at end of file +PRECOMPILE_BLAKE2F_ROUNDS = 512 + +PRECOMPILE_BLAKE2F = 512 +PRECOMPILE_ECADD = 512 +PRECOMPILE_ECMUL = 512 +PRECOMPILE_ECPAIRING = 512 +PRECOMPILE_ECRECOVER = 512 +PRECOMPILE_MODEXP = 512 +PRECOMPILE_RIPEMD = 512 +PRECOMPILE_SHA2 = 512 \ No newline at end of file diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/ZkTracer.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/ZkTracer.java index 747a180329..80a8e7b653 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/ZkTracer.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/ZkTracer.java @@ -166,7 +166,7 @@ public void traceEndBlock(final BlockHeader blockHeader, final BlockBody blockBo } @Override - public void tracePrepareTransaction(WorldView worldView, Transaction transaction) { + public void traceStartTransaction(WorldView worldView, Transaction transaction) { hashOfLastTransactionTraced = transaction.getHash(); this.hub.traceStartTx(worldView, transaction); } diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/Util.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/Util.java index 4a78d9c33b..d7b2624f90 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/Util.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/Util.java @@ -27,6 +27,9 @@ /** Utility class that provides various helper methods. */ public class Util { + public static long roundedUpDivision(long x, long anchor) { + return (x + anchor - 1) / anchor; + } /** * Converts the bits of an unsigned byte into an array of Booleans. diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/add/Add.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/add/Add.java index 66bf1d97a1..5c79e2b136 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/add/Add.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/add/Add.java @@ -70,6 +70,6 @@ public void commit(List buffers) { @Override public int lineCount() { - return this.chunks.lineCount(); + return this.chunks.size() * 16; } } diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java index 8e29850d97..6233d19596 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java @@ -41,16 +41,18 @@ import net.consensys.linea.zktracer.module.hub.fragment.*; import net.consensys.linea.zktracer.module.hub.fragment.misc.MiscFragment; import net.consensys.linea.zktracer.module.hub.section.*; +import net.consensys.linea.zktracer.module.legacy.hash.HashData; +import net.consensys.linea.zktracer.module.legacy.hash.HashInfo; import net.consensys.linea.zktracer.module.limits.Keccak; import net.consensys.linea.zktracer.module.limits.L2Block; import net.consensys.linea.zktracer.module.limits.L2L1Logs; import net.consensys.linea.zktracer.module.limits.precompiles.Blake2fRounds; import net.consensys.linea.zktracer.module.limits.precompiles.EcAddEffectiveCall; import net.consensys.linea.zktracer.module.limits.precompiles.EcMulEffectiveCall; -import net.consensys.linea.zktracer.module.limits.precompiles.EcPairingCallEffectiveCall; +import net.consensys.linea.zktracer.module.limits.precompiles.EcPairingEffectiveCall; import net.consensys.linea.zktracer.module.limits.precompiles.EcPairingMillerLoop; import net.consensys.linea.zktracer.module.limits.precompiles.EcRecoverEffectiveCall; -import net.consensys.linea.zktracer.module.limits.precompiles.ModexpEffectiveCall; +import net.consensys.linea.zktracer.module.limits.precompiles.Modexp; import net.consensys.linea.zktracer.module.limits.precompiles.Rip160Blocks; import net.consensys.linea.zktracer.module.limits.precompiles.Sha256Blocks; import net.consensys.linea.zktracer.module.logData.LogData; @@ -184,9 +186,20 @@ public void addTraceSection(TraceSection section) { private final RomLex romLex; private final TxnData txnData; private final Trm trm = new Trm(); - private final ModexpEffectiveCall modexp; private final Stp stp = new Stp(this, wcp, mod); private final L2Block l2Block; + private final HashInfo hashInfo; + private final HashData hashData; + + // Precompiles stuff + Blake2fRounds blake2f; + EcAddEffectiveCall ecAdd; + EcMulEffectiveCall ecMul; + EcPairingEffectiveCall ecPairing; + EcRecoverEffectiveCall ecRecover; + Modexp modexp; + Rip160Blocks rip160; + Sha256Blocks sha256; private final List modules; /* Those modules are not traced, we just compute the number of calls to those precompile to meet the prover limits */ @@ -204,24 +217,46 @@ public Hub(final Address l2l1ContractAddress, final Bytes l2l1Topic) { this.txnData = new TxnData(this, this.romLex, this.wcp); this.ecData = new EcData(this, this.wcp, this.ext); this.euc = new Euc(this.wcp); + this.hashData = new HashData(this); + this.hashInfo = new HashInfo(this); + + // + // Precompiles + // + this.blake2f = new Blake2fRounds(this); + this.ecAdd = new EcAddEffectiveCall(this); + this.ecMul = new EcMulEffectiveCall(this); + this.ecPairing = new EcPairingEffectiveCall(this); + this.ecRecover = new EcRecoverEffectiveCall(this); + this.modexp = new Modexp(this); + this.rip160 = new Rip160Blocks(this); + this.sha256 = new Sha256Blocks(this); - final EcRecoverEffectiveCall ecRec = new EcRecoverEffectiveCall(this); - this.modexp = new ModexpEffectiveCall(this); - final EcPairingCallEffectiveCall ecpairingCall = new EcPairingCallEffectiveCall(this); this.precompileLimitModules = List.of( - new Sha256Blocks(this), - ecRec, - new Rip160Blocks(this), + this.blake2f, + this.blake2f.callCounter(), + this.ecAdd, + this.ecAdd.callCounter(), + this.ecMul, + this.ecMul.callCounter(), + this.ecPairing, + this.ecPairing.callCounter(), + new EcPairingMillerLoop(this.ecPairing), + this.ecRecover, + this.ecRecover.callCounter(), this.modexp, - new EcAddEffectiveCall(this), - new EcMulEffectiveCall(this), - ecpairingCall, - new EcPairingMillerLoop(ecpairingCall), - new Blake2fRounds(this), + this.modexp.callCounter(), + this.rip160, + this.rip160.callCounter(), + this.sha256, + this.sha256.callCounter(), + // Block level limits + this.hashData, + this.hashInfo, this.l2Block, - new Keccak(this, ecRec, this.l2Block), + new Keccak(this, this.ecRecover, this.l2Block), new L2L1Logs(this.l2Block)); this.refTableModules = List.of(new BinRt(), new InstructionDecoder(), new ShfRt()); @@ -257,32 +292,36 @@ public Hub(final Address l2l1ContractAddress, final Bytes l2l1Topic) { * @return a list of all modules for which to generate traces */ public List getModulesToTrace() { - return Stream.concat( - this.refTableModules.stream(), - // Modules - Stream.of( - this, - this.romLex, - this.add, - this.bin, - this.ext, - // this.ecData, // TODO: not yet - this.euc, - this.logData, - this.logInfo, - this.mod, - this.modexp.data(), - this.mul, - this.mxp, - this.rlpAddr, - this.rlpTxn, - this.rlpTxrcpt, - this.rom, - this.shf, - this.stp, - this.txnData, - this.wcp)) - .toList(); + return List.of( + // + // Reference tables + // + new BinRt(), + new InstructionDecoder(), + new ShfRt(), + // + // Modules + // + this, + this.add, + this.bin, + this.ext, + // this.ecData, // TODO: not yet + this.euc, + this.logData, + this.logInfo, + this.mod, + this.mul, + this.mxp, + this.rlpAddr, + this.rlpTxn, + this.rlpTxrcpt, + this.rom, + this.romLex, + this.shf, + this.stp, + // this.txnData, + this.wcp); } public List getModulesToCount() { @@ -307,8 +346,10 @@ public List getModulesToCount() { this.rom, this.shf, this.trm, - this.txnData, - this.wcp), + // this.txnData, + this.wcp, + this.hashData, + this.hashInfo), this.precompileLimitModules.stream()) .toList(); } @@ -519,7 +560,7 @@ void triggerModules(MessageFrame frame) { // TODO: this.oob.tracePreOpcode(frame); } if (this.pch.signals().stp()) { - this.stp.tracePreOpcode(frame); + // this.stp.tracePreOpcode(frame); } if (this.pch.signals().exp()) { this.modexp.tracePreOpcode(frame); diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/TxTrace.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/TxTrace.java index 2745fc4cb0..f26dd8c9e2 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/TxTrace.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/hub/TxTrace.java @@ -118,8 +118,8 @@ public void commit(Trace hubTrace) { */ public int lineCount() { if (this.cachedLineCount == 0) { - for (TraceSection s : trace) { - this.cachedLineCount += s.getLines().size(); + for (TraceSection section : this.trace) { + this.cachedLineCount += section.getStackRowsCounter(); } } return this.cachedLineCount; diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/legacy/hash/HashData.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/legacy/hash/HashData.java new file mode 100644 index 0000000000..1ab9a862b7 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/legacy/hash/HashData.java @@ -0,0 +1,77 @@ +/* + * Copyright ConsenSys AG. + * + * 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.legacy.hash; + +import static net.consensys.linea.zktracer.module.Util.roundedUpDivision; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import net.consensys.linea.zktracer.ColumnHeader; +import net.consensys.linea.zktracer.module.Module; +import net.consensys.linea.zktracer.module.hub.Hub; +import net.consensys.linea.zktracer.opcode.OpCode; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.internal.Words; + +@RequiredArgsConstructor +public class HashData implements Module { + private final Hub hub; + private final Deque state = new ArrayDeque<>(); + + @Override + public String moduleKey() { + return "PUB_HASH"; + } + + @Override + public void enterTransaction() { + this.state.push(0); + } + + @Override + public void popTransaction() { + this.state.pop(); + } + + @Override + public int lineCount() { + return this.state.stream().mapToInt(x -> x).sum(); + } + + @Override + public List columnsHeaders() { + throw new IllegalStateException("should never be called"); + } + + private void add(int x) { + this.state.push(this.state.pop() + x); + } + + @Override + public void tracePreOpcode(MessageFrame frame) { + final OpCode opCode = hub.opCode(); + if (opCode == OpCode.CREATE2 || opCode == OpCode.SHA3) { + if (this.hub.pch().exceptions().none()) { + final long size = Words.clampedToLong(frame.getStackItem(1)); + final int limbCount = (int) roundedUpDivision(size, 16); + this.add(limbCount); + } + } + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/legacy/hash/HashInfo.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/legacy/hash/HashInfo.java new file mode 100644 index 0000000000..60c4a48b81 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/legacy/hash/HashInfo.java @@ -0,0 +1,72 @@ +/* + * Copyright ConsenSys AG. + * + * 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.legacy.hash; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import net.consensys.linea.zktracer.ColumnHeader; +import net.consensys.linea.zktracer.module.Module; +import net.consensys.linea.zktracer.module.hub.Hub; +import net.consensys.linea.zktracer.opcode.OpCode; +import org.hyperledger.besu.evm.frame.MessageFrame; + +@RequiredArgsConstructor +public class HashInfo implements Module { + private final Hub hub; + private final Deque state = new ArrayDeque<>(); + + @Override + public String moduleKey() { + return "PUB_HASH_INFO"; + } + + @Override + public void enterTransaction() { + this.state.push(0); + } + + @Override + public void popTransaction() { + this.state.pop(); + } + + @Override + public int lineCount() { + return this.state.stream().mapToInt(x -> x).sum(); + } + + @Override + public List columnsHeaders() { + throw new IllegalStateException("should never be called"); + } + + private void add(int x) { + this.state.push(this.state.pop() + x); + } + + @Override + public void tracePreOpcode(MessageFrame frame) { + final OpCode opCode = hub.opCode(); + if (opCode == OpCode.CREATE2 || opCode == OpCode.SHA3) { + if (this.hub.pch().exceptions().none()) { + this.add(1); + } + } + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/AbstractCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/AbstractCallCounter.java new file mode 100644 index 0000000000..17bae8215e --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/AbstractCallCounter.java @@ -0,0 +1,57 @@ +/* + * Copyright ConsenSys AG. + * + * 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.limits.precompiles; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; + +import net.consensys.linea.zktracer.ColumnHeader; +import net.consensys.linea.zktracer.module.Module; +import org.apache.commons.lang3.NotImplementedException; + +public class AbstractCallCounter implements Module { + private final Deque callCount = new ArrayDeque<>(); + + @Override + public String moduleKey() { + throw new NotImplementedException("must be implemented by derived class"); + } + + @Override + public void enterTransaction() { + this.callCount.push(0); + } + + @Override + public void popTransaction() { + this.callCount.pop(); + } + + @Override + public int lineCount() { + return this.callCount.stream().mapToInt(x -> x).sum(); + } + + public void tick() { + this.callCount.push(this.callCount.pop() + 1); + } + + @Override + public List columnsHeaders() { + throw new IllegalStateException("should never be called"); + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fCallCounter.java new file mode 100644 index 0000000000..c33ea10475 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fCallCounter.java @@ -0,0 +1,23 @@ +/* + * Copyright ConsenSys AG. + * + * 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.limits.precompiles; + +public class Blake2fCallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_BLAKE2F"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fRounds.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fRounds.java index 035d748713..f631772c17 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fRounds.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Blake2fRounds.java @@ -30,9 +30,14 @@ @RequiredArgsConstructor public final class Blake2fRounds implements Module { - final Hub hub; + private final Hub hub; + private final Blake2fCallCounter blake2fCallCounter = new Blake2fCallCounter(); private final Stack counts = new Stack<>(); + public Module callCounter() { + return this.blake2fCallCounter; + } + @Override public String moduleKey() { return "PRECOMPILE_BLAKE2F_ROUNDS"; @@ -56,6 +61,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.BLAKE2B_F_COMPRESSION)) { + this.blake2fCallCounter.tick(); long length = 0; long offset = 0; switch (opCode) { diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddCallCounter.java new file mode 100644 index 0000000000..06037849f8 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddCallCounter.java @@ -0,0 +1,23 @@ +/* + * Copyright ConsenSys AG. + * + * 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.limits.precompiles; + +public class EcAddCallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_ECADD"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddEffectiveCall.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddEffectiveCall.java index 8ddea82976..497d035cb5 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddEffectiveCall.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcAddEffectiveCall.java @@ -31,8 +31,13 @@ @RequiredArgsConstructor public final class EcAddEffectiveCall implements Module { private final Hub hub; + private final EcAddCallCounter ecAddCallCounter = new EcAddCallCounter(); private final Stack counts = new Stack<>(); + public Module callCounter() { + return this.ecAddCallCounter; + } + @Override public String moduleKey() { return "PRECOMPILE_ECADD_EFFECTIVE_CALL"; @@ -58,6 +63,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.ALTBN128_ADD)) { + this.ecAddCallCounter.tick(); final long gasPaid = Words.clampedToLong(frame.getStackItem(0)); if (gasPaid >= PRECOMPILE_GAS_FEE) { this.counts.push(this.counts.pop() + 1); diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulCallCounter.java new file mode 100644 index 0000000000..3e5bf0fd77 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulCallCounter.java @@ -0,0 +1,23 @@ +/* + * Copyright ConsenSys AG. + * + * 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.limits.precompiles; + +public class EcMulCallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_ECMUL"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulEffectiveCall.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulEffectiveCall.java index ac45cedc1f..29f19b3f57 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulEffectiveCall.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcMulEffectiveCall.java @@ -1,4 +1,5 @@ /* + * Copyright ConsenSys Inc. * Copyright Consensys Software Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with @@ -31,8 +32,13 @@ @RequiredArgsConstructor public final class EcMulEffectiveCall implements Module { private final Hub hub; + private final EcMulCallCounter ecMulCallCounter = new EcMulCallCounter(); private final Stack counts = new Stack<>(); + public Module callCounter() { + return this.ecMulCallCounter; + } + @Override public String moduleKey() { return "PRECOMPILE_ECMUL_EFFECTIVE_CALL"; @@ -58,6 +64,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.ALTBN128_MUL)) { + this.ecMulCallCounter.tick(); final long gasPaid = Words.clampedToLong(frame.getStackItem(0)); if (gasPaid >= PRECOMPILE_GAS_FEE) { this.counts.push(this.counts.pop() + 1); diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingCallCounter.java new file mode 100644 index 0000000000..4b41000913 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingCallCounter.java @@ -0,0 +1,23 @@ +/* + * 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.limits.precompiles; + +public final class EcPairingCallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_ECPAIRING"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingCallEffectiveCall.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingEffectiveCall.java similarity index 92% rename from arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingCallEffectiveCall.java rename to arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingEffectiveCall.java index 71a8efca72..78c1a98218 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingCallEffectiveCall.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingEffectiveCall.java @@ -32,13 +32,18 @@ @Slf4j @RequiredArgsConstructor -public final class EcPairingCallEffectiveCall implements Module { +public final class EcPairingEffectiveCall implements Module { private final Hub hub; + private final EcPairingCallCounter ecPairingCallCounter = new EcPairingCallCounter(); @Getter private final Stack counts = new Stack<>(); private static final int PRECOMPILE_BASE_GAS_FEE = 45000; // cf EIP-1108 private static final int PRECOMPILE_MILLER_LOOP_GAS_FEE = 34000; // cf EIP-1108 private static final int ECPAIRING_NB_BYTES_PER_MILLER_LOOP = 192; + public Module callCounter() { + return this.ecPairingCallCounter; + } + @Override public String moduleKey() { return "PRECOMPILE_ECPAIRING_EFFECTIVE_CALL"; @@ -62,6 +67,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.ALTBN128_PAIRING)) { + this.ecPairingCallCounter.tick(); long length = 0; switch (opCode) { case CALL, CALLCODE -> length = Words.clampedToLong(frame.getStackItem(4)); diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingMillerLoop.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingMillerLoop.java index ff0fd622fd..f1de3d2071 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingMillerLoop.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcPairingMillerLoop.java @@ -22,9 +22,9 @@ import net.consensys.linea.zktracer.module.Module; public final class EcPairingMillerLoop implements Module { - private final EcPairingCallEffectiveCall ecpairingCall; + private final EcPairingEffectiveCall ecpairingCall; - public EcPairingMillerLoop(EcPairingCallEffectiveCall ecpairingCall) { + public EcPairingMillerLoop(EcPairingEffectiveCall ecpairingCall) { this.ecpairingCall = ecpairingCall; } diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverCallCounter.java new file mode 100644 index 0000000000..81e741c1ec --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverCallCounter.java @@ -0,0 +1,23 @@ +/* + * Copyright ConsenSys AG. + * + * 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.limits.precompiles; + +public class EcRecoverCallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_ECRECOVER"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverEffectiveCall.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverEffectiveCall.java index 904880f120..032f083a3b 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverEffectiveCall.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/EcRecoverEffectiveCall.java @@ -35,8 +35,13 @@ @RequiredArgsConstructor public final class EcRecoverEffectiveCall implements Module { private final Hub hub; + private final EcRecoverCallCounter ecRecoverCallCounter = new EcRecoverCallCounter(); private final Stack counts = new Stack<>(); + public Module callCounter() { + return this.ecRecoverCallCounter; + } + @Override public String moduleKey() { return "PRECOMPILE_ECRECOVER_EFFECTIVE_CALL"; @@ -66,6 +71,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.ECREC)) { + this.ecRecoverCallCounter.tick(); long length = 0; long offset = 0; switch (opCode) { diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/ModExpCallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/ModExpCallCounter.java new file mode 100644 index 0000000000..fdb1f1d825 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/ModExpCallCounter.java @@ -0,0 +1,23 @@ +/* + * 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.limits.precompiles; + +public final class ModExpCallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_MODEXP"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Modexp.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Modexp.java new file mode 100644 index 0000000000..d98de78310 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Modexp.java @@ -0,0 +1,200 @@ +/* + * Copyright Consensys Software 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.limits.precompiles; + +import static net.consensys.linea.zktracer.module.Util.slice; + +import java.math.BigInteger; +import java.nio.MappedByteBuffer; +import java.util.List; +import java.util.Stack; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.consensys.linea.zktracer.ColumnHeader; +import net.consensys.linea.zktracer.module.Module; +import net.consensys.linea.zktracer.module.hub.Hub; +import net.consensys.linea.zktracer.opcode.OpCode; +import org.apache.tuweni.bytes.Bytes; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.internal.Words; + +@Slf4j +@RequiredArgsConstructor +public class Modexp implements Module { + private final Hub hub; + public final ModExpCallCounter modExpCallCounter = new ModExpCallCounter(); + private final Stack counts = new Stack<>(); + private static final BigInteger PROVER_MAX_INPUT_BIT_SIZE = BigInteger.valueOf(4096); + private static final int EVM_WORD_SIZE = 32; + + public Module callCounter() { + return this.modExpCallCounter; + } + + @Override + public String moduleKey() { + return "PRECOMPILE_MODEXP_EFFECTIVE_CALL"; + } + + @Override + public void enterTransaction() { + counts.push(0); + } + + @Override + public void popTransaction() { + counts.pop(); + } + + @Override + public void tracePreOpcode(MessageFrame frame) { + final OpCode opCode = hub.opCode(); + + switch (opCode) { + case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { + final Address target = Words.toAddress(frame.getStackItem(1)); + if (target.equals(Address.MODEXP)) { + this.modExpCallCounter.tick(); + long length = 0; + long offset = 0; + switch (opCode) { + case CALL, CALLCODE -> { + length = Words.clampedToLong(frame.getStackItem(4)); + offset = Words.clampedToLong(frame.getStackItem(3)); + } + case DELEGATECALL, STATICCALL -> { + length = Words.clampedToLong(frame.getStackItem(3)); + offset = Words.clampedToLong(frame.getStackItem(2)); + } + } + + final Bytes inputData = frame.shadowReadMemory(offset, length); + + // Get the Base length + final BigInteger baseLength = slice(inputData, 0, EVM_WORD_SIZE).toUnsignedBigInteger(); + if (isInProverInputBounds(baseLength)) { + log.info( + "Too big argument, base bit length = {} > {}", + baseLength, + PROVER_MAX_INPUT_BIT_SIZE); + this.counts.pop(); + this.counts.push(Integer.MAX_VALUE); + return; + } + + // Get the Exponent length + final BigInteger expLength = + slice(inputData, EVM_WORD_SIZE, EVM_WORD_SIZE).toUnsignedBigInteger(); + if (isInProverInputBounds(expLength)) { + log.info( + "Too big argument, expComponent bit length = {} > {}", + expLength, + PROVER_MAX_INPUT_BIT_SIZE); + this.counts.pop(); + this.counts.push(Integer.MAX_VALUE); + return; + } + + // Get the Modulo length + final BigInteger modLength = + slice(inputData, 2 * EVM_WORD_SIZE, EVM_WORD_SIZE).toUnsignedBigInteger(); + if (isInProverInputBounds(modLength)) { + log.info( + "Too big argument, modulo bit length = {} > {}", + modLength, + PROVER_MAX_INPUT_BIT_SIZE); + this.counts.pop(); + this.counts.push(Integer.MAX_VALUE); + return; + } + + final int baseLengthInt = baseLength.intValueExact(); + final int expLengthInt = expLength.intValueExact(); + final int modLengthInt = modLength.intValueExact(); + + // Get the Base. + final Bytes baseComponent = slice(inputData, 3 * EVM_WORD_SIZE, baseLengthInt); + + // Get the Exponent. + final Bytes expComponent = + slice(inputData, 3 * EVM_WORD_SIZE + baseLengthInt, expLength.intValueExact()); + + // Get the Modulus. + final Bytes modComponent = + slice( + inputData, + 3 * EVM_WORD_SIZE + baseLengthInt + expLengthInt, + modLength.intValueExact()); + + final long gasPaid = Words.clampedToLong(frame.getStackItem(0)); + final long gasPrice = gasPrice(baseLengthInt, expLengthInt, modLengthInt, expComponent); + + // If enough gas, add 1 to the call of the precompile. + if (gasPaid >= gasPrice) { + this.counts.push(this.counts.pop() + 1); + } + } + } + } + } + + private long gasPrice(int baseLength, int expLength, int moduloLength, Bytes e) { + final long maxLbLmSquared = + (long) Math.sqrt((double) (Math.max(baseLength, moduloLength) + 7) / 8); + final long secondArg = (maxLbLmSquared * expLengthPrime(expLength, e)) / 3; + + return Math.max(200, secondArg); + } + + private int expLengthPrime(int expLength, Bytes e) { + if (expLength <= 32) { + if (e.toUnsignedBigInteger().equals(BigInteger.ZERO)) { + return 0; + } + return e.toUnsignedBigInteger().bitLength() - 1; + } else if (e.slice(0, EVM_WORD_SIZE).toUnsignedBigInteger().compareTo(BigInteger.ZERO) != 0) { + return 8 * (expLength - 32) + + e.slice(0, EVM_WORD_SIZE).toUnsignedBigInteger().bitLength() + - 1; + } + + return 8 * (expLength - 32); + } + + private boolean isInProverInputBounds(BigInteger modexpComponentLength) { + return modexpComponentLength + .multiply(BigInteger.valueOf(8)) + .compareTo(PROVER_MAX_INPUT_BIT_SIZE) + > 0; + } + + @Override + public int lineCount() { + return this.counts.stream().mapToInt(x -> x).sum(); + } + + @Override + public List columnsHeaders() { + throw new UnsupportedOperationException("should never be called"); + } + + @Override + public void commit(List buffers) { + throw new UnsupportedOperationException("should never be called"); + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/ModexpEffectiveCall.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/ModexpEffectiveCall.java deleted file mode 100644 index f8590f309c..0000000000 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/ModexpEffectiveCall.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright Consensys Software 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.limits.precompiles; - -import static net.consensys.linea.zktracer.module.Util.slice; - -import java.math.BigInteger; -import java.nio.MappedByteBuffer; -import java.util.List; -import java.util.Stack; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.experimental.Accessors; -import lombok.extern.slf4j.Slf4j; -import net.consensys.linea.zktracer.ColumnHeader; -import net.consensys.linea.zktracer.module.Module; -import net.consensys.linea.zktracer.module.hub.Hub; -import net.consensys.linea.zktracer.module.modexpdata.ModexpData; -import net.consensys.linea.zktracer.module.modexpdata.ModexpDataOperation; -import net.consensys.linea.zktracer.opcode.OpCode; -import org.apache.tuweni.bytes.Bytes; -import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.evm.frame.MessageFrame; -import org.hyperledger.besu.evm.internal.Words; - -@Slf4j -@RequiredArgsConstructor -@Accessors(fluent = true) -public class ModexpEffectiveCall implements Module { - private final Hub hub; - - @Getter private final ModexpData data = new ModexpData(); - private final Stack counts = new Stack<>(); - private static final BigInteger PROVER_MAX_INPUT_BIT_SIZE = BigInteger.valueOf(4096); - private static final int EVM_WORD_SIZE = 32; - - private int lastModexpDataCallHubStamp = 0; - - @Override - public String moduleKey() { - return "PRECOMPILE_MODEXP_EFFECTIVE_CALL"; - } - - @Override - public void enterTransaction() { - counts.push(0); - } - - @Override - public void popTransaction() { - counts.pop(); - } - - @Override - public void tracePreOpcode(MessageFrame frame) { - final OpCode opCode = hub.opCode(); - - if (opCode.isAnyOf(OpCode.CALL, OpCode.STATICCALL, OpCode.DELEGATECALL, OpCode.CALLCODE)) { - final Address target = Words.toAddress(frame.getStackItem(1)); - if (target.equals(Address.MODEXP)) { - long length = 0; - long offset = 0; - switch (opCode) { - case CALL, CALLCODE -> { - length = Words.clampedToLong(frame.getStackItem(4)); - offset = Words.clampedToLong(frame.getStackItem(3)); - } - case DELEGATECALL, STATICCALL -> { - length = Words.clampedToLong(frame.getStackItem(3)); - offset = Words.clampedToLong(frame.getStackItem(2)); - } - } - final Bytes inputData = frame.shadowReadMemory(offset, length); - - // Get the Base length - final BigInteger baseLength = slice(inputData, 0, EVM_WORD_SIZE).toUnsignedBigInteger(); - if (isInProverInputBounds(baseLength)) { - log.info( - "Too big argument, base bit length = {} > {}", baseLength, PROVER_MAX_INPUT_BIT_SIZE); - this.counts.pop(); - this.counts.push(Integer.MAX_VALUE); - return; - } - - // Get the Exponent length - final BigInteger expLength = - slice(inputData, EVM_WORD_SIZE, EVM_WORD_SIZE).toUnsignedBigInteger(); - if (isInProverInputBounds(expLength)) { - log.info( - "Too big argument, expComponent bit length = {} > {}", - expLength, - PROVER_MAX_INPUT_BIT_SIZE); - this.counts.pop(); - this.counts.push(Integer.MAX_VALUE); - return; - } - - // Get the Modulo length - final BigInteger modLength = - slice(inputData, 2 * EVM_WORD_SIZE, EVM_WORD_SIZE).toUnsignedBigInteger(); - if (isInProverInputBounds(modLength)) { - log.info( - "Too big argument, modulo bit length = {} > {}", - modLength, - PROVER_MAX_INPUT_BIT_SIZE); - this.counts.pop(); - this.counts.push(Integer.MAX_VALUE); - return; - } - - final int baseLengthInt = baseLength.intValueExact(); - final int expLengthInt = expLength.intValueExact(); - final int modLengthInt = modLength.intValueExact(); - - // Get the Base. - final Bytes baseComponent = slice(inputData, 3 * EVM_WORD_SIZE, baseLengthInt); - - // Get the Exponent. - final Bytes expComponent = - slice(inputData, 3 * EVM_WORD_SIZE + baseLengthInt, expLength.intValueExact()); - - // Get the Modulus. - final Bytes modComponent = - slice( - inputData, - 3 * EVM_WORD_SIZE + baseLengthInt + expLengthInt, - modLength.intValueExact()); - - final long gasPaid = Words.clampedToLong(frame.getStackItem(0)); - final long gasPrice = gasPrice(baseLengthInt, expLengthInt, modLengthInt, expComponent); - - // If enough gas, add 1 to the call of the precompile. - if (gasPaid >= gasPrice) { - this.lastModexpDataCallHubStamp = - this.data.call( - new ModexpDataOperation( - hub.stamp(), - lastModexpDataCallHubStamp, - baseComponent, - expComponent, - modComponent)); - this.counts.push(this.counts.pop() + 1); - } - } - } - } - - private long gasPrice(int baseLength, int expLength, int moduloLength, Bytes e) { - final long maxLbLmSquared = - (long) Math.sqrt((double) (Math.max(baseLength, moduloLength) + 7) / 8); - final long secondArg = (maxLbLmSquared * expLengthPrime(expLength, e)) / 3; - - return Math.max(200, secondArg); - } - - private int expLengthPrime(int expLength, Bytes e) { - if (expLength <= 32) { - if (e.toUnsignedBigInteger().equals(BigInteger.ZERO)) { - return 0; - } - return e.toUnsignedBigInteger().bitLength() - 1; - } else if (e.slice(0, EVM_WORD_SIZE).toUnsignedBigInteger().compareTo(BigInteger.ZERO) != 0) { - return 8 * (expLength - 32) - + e.slice(0, EVM_WORD_SIZE).toUnsignedBigInteger().bitLength() - - 1; - } - - return 8 * (expLength - 32); - } - - private boolean isInProverInputBounds(BigInteger modexpComponentLength) { - return modexpComponentLength - .multiply(BigInteger.valueOf(8)) - .compareTo(PROVER_MAX_INPUT_BIT_SIZE) - > 0; - } - - @Override - public int lineCount() { - return this.counts.stream().mapToInt(x -> x).sum(); - } - - @Override - public List columnsHeaders() { - throw new UnsupportedOperationException("should never be called"); - } - - @Override - public void commit(List buffers) { - throw new UnsupportedOperationException("should never be called"); - } -} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160Blocks.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160Blocks.java index aa4b5c328a..e4092cecad 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160Blocks.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160Blocks.java @@ -31,6 +31,7 @@ @RequiredArgsConstructor public final class Rip160Blocks implements Module { private final Hub hub; + private final Rip160CallCounter rip160CallCounter = new Rip160CallCounter(); private final Stack counts = new Stack<>(); @Override @@ -45,6 +46,10 @@ public String moduleKey() { private static final int RIPEMD160_LENGTH_APPEND = 64; private static final int RIPEMD160_ND_PADDED_ONE = 1; + public Module callCounter() { + return this.rip160CallCounter; + } + @Override public void enterTransaction() { counts.push(0); @@ -63,6 +68,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.RIPEMD160)) { + this.rip160CallCounter.tick(); long dataByteLength = 0; switch (opCode) { case CALL, CALLCODE -> dataByteLength = Words.clampedToLong(frame.getStackItem(4)); diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160CallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160CallCounter.java new file mode 100644 index 0000000000..b16ee2f604 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Rip160CallCounter.java @@ -0,0 +1,23 @@ +/* + * 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.limits.precompiles; + +public final class Rip160CallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_RIPEMD"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256Blocks.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256Blocks.java index 4fba3b5089..3437f61964 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256Blocks.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256Blocks.java @@ -31,6 +31,7 @@ @RequiredArgsConstructor public final class Sha256Blocks implements Module { private final Hub hub; + private final Sha256CallCounter sha256CallCounter = new Sha256CallCounter(); private final Stack counts = new Stack<>(); @Override @@ -45,6 +46,10 @@ public String moduleKey() { private static final int SHA256_PADDING_LENGTH = 64; private static final int SHA256_NB_PADDED_ONE = 1; + public Module callCounter() { + return this.sha256CallCounter; + } + @Override public void enterTransaction() { counts.push(0); @@ -63,6 +68,7 @@ public void tracePreOpcode(MessageFrame frame) { case CALL, STATICCALL, DELEGATECALL, CALLCODE -> { final Address target = Words.toAddress(frame.getStackItem(1)); if (target.equals(Address.SHA256)) { + this.sha256CallCounter.tick(); long dataByteLength = 0; switch (opCode) { case CALL, CALLCODE -> dataByteLength = Words.clampedToLong(frame.getStackItem(4)); diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256CallCounter.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256CallCounter.java new file mode 100644 index 0000000000..20a2e53943 --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/limits/precompiles/Sha256CallCounter.java @@ -0,0 +1,23 @@ +/* + * 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.limits.precompiles; + +public final class Sha256CallCounter extends AbstractCallCounter { + @Override + public String moduleKey() { + return "PRECOMPILE_SHA2"; + } +} diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rlp/addr/RlpAddr.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rlp/addr/RlpAddr.java index f17c7c16a2..2f3c3fc7b3 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rlp/addr/RlpAddr.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rlp/addr/RlpAddr.java @@ -282,7 +282,7 @@ private void traceChunks(RlpAddrChunk chunk, int stamp, Trace trace) { @Override public int lineCount() { - return this.chunkList.lineCount(); + return 2 * (this.chunkList.lineCount() + 1); } @Override diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rom/Rom.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rom/Rom.java index c0ff698f67..57f61bdb00 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rom/Rom.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/rom/Rom.java @@ -43,7 +43,15 @@ public void popTransaction() {} @Override public int lineCount() { - return this.romLex.chunks.lineCount(); + int traceRowSize = 0; + for (RomChunk chunk : this.romLex.chunks) { + traceRowSize += chunkRowSize(chunk); + } + return traceRowSize + 32 * this.romLex.emptyContractsCount.stream().mapToInt(x -> x).sum(); + } + + public int chunkRowSize(RomChunk chunk) { + return chunk.byteCode().size(); } @Override diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/romLex/RomLex.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/romLex/RomLex.java index 95671e73b8..5d162a1a2c 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/romLex/RomLex.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/romLex/RomLex.java @@ -20,8 +20,10 @@ import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import java.nio.MappedByteBuffer; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Comparator; +import java.util.Deque; import java.util.List; import java.util.Optional; @@ -47,6 +49,7 @@ public class RomLex implements Module { public int codeIdentifierBeforeLexOrder = 0; public final StackedSet chunks = new StackedSet<>(); + public final Deque emptyContractsCount = new ArrayDeque<>(); public final List sortedChunks = new ArrayList<>(); private Bytes byteCode = Bytes.EMPTY; private Address address = Address.ZERO; @@ -87,11 +90,13 @@ public RomLex(Hub hub) { @Override public void enterTransaction() { this.chunks.enter(); + this.emptyContractsCount.push(0); } @Override public void popTransaction() { this.chunks.pop(); + this.emptyContractsCount.pop(); } public int getCFIById(int value) { @@ -133,7 +138,7 @@ public void traceStartTx(WorldView worldView, Transaction tx) { tx.getTo() .map(worldView::get) .map(AccountState::getCode) - .ifPresent( + .ifPresentOrElse( code -> { codeIdentifierBeforeLexOrder += 1; int depNumber = hub.conflation().deploymentInfo().number(tx.getTo().get()); @@ -148,7 +153,8 @@ public void traceStartTx(WorldView worldView, Transaction tx) { true, false, code)); - }); + }, + () -> this.emptyContractsCount.push(this.emptyContractsCount.pop() + 1)); } @Override @@ -183,7 +189,7 @@ public void tracePreOpcode(MessageFrame frame) { final Bytes code = frame.shadowReadMemory(offset, length); final boolean depStatus = hub.conflation().deploymentInfo().isDeploying(frame.getContractAddress()); - if (!code.isEmpty() && depStatus) { + if (depStatus) { codeIdentifierBeforeLexOrder += 1; int depNumber = hub.conflation().deploymentInfo().number(frame.getContractAddress()); this.chunks.add( @@ -205,7 +211,7 @@ public void tracePreOpcode(MessageFrame frame) { final int depNumber = hub.conflation().deploymentInfo().number(frame.getContractAddress()); Optional.ofNullable(frame.getWorldUpdater().get(calledAddress)) .map(AccountState::getCode) - .ifPresent( + .ifPresentOrElse( byteCode -> { codeIdentifierBeforeLexOrder += 1; this.chunks.add( @@ -217,7 +223,8 @@ public void tracePreOpcode(MessageFrame frame) { true, false, byteCode)); - }); + }, + () -> this.emptyContractsCount.push(this.emptyContractsCount.pop() + 1)); } case EXTCODECOPY -> { @@ -231,7 +238,7 @@ public void tracePreOpcode(MessageFrame frame) { final int depNumber = hub.conflation().deploymentInfo().number(frame.getContractAddress()); Optional.ofNullable(frame.getWorldUpdater().get(calledAddress)) .map(AccountState::getCode) - .ifPresent( + .ifPresentOrElse( byteCode -> { if (!byteCode.isEmpty()) { codeIdentifierBeforeLexOrder += 1; @@ -245,7 +252,8 @@ public void tracePreOpcode(MessageFrame frame) { false, byteCode)); } - }); + }, + () -> this.emptyContractsCount.push(this.emptyContractsCount.pop() + 1)); } } } @@ -269,6 +277,7 @@ public void tracePostExecution(MessageFrame frame, Operation.OperationResult ope this.byteCode)); } } + this.byteCode = Bytes.EMPTY; } private void traceChunk( diff --git a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/wcp/WcpOperation.java b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/wcp/WcpOperation.java index 44797cf77d..1376491865 100644 --- a/arithmetization/src/main/java/net/consensys/linea/zktracer/module/wcp/WcpOperation.java +++ b/arithmetization/src/main/java/net/consensys/linea/zktracer/module/wcp/WcpOperation.java @@ -237,6 +237,7 @@ private int maxCt() { @Override protected int computeLineCount() { - return this.ctMax + 1; + final boolean isOli = (wcpInst == 0x14 /* EQ */) || (wcpInst == 0x15 /* ISZERO */); + return isOli ? 1 : 16; } } diff --git a/arithmetization/src/main/resources/spillings.toml b/arithmetization/src/main/resources/spillings.toml index d4d5fece87..d486794869 100644 --- a/arithmetization/src/main/resources/spillings.toml +++ b/arithmetization/src/main/resources/spillings.toml @@ -6,7 +6,9 @@ EC_DATA = 12 EUC = 1 EXT = 8 PUB_HASH = 0 +OLD_PUB_HASH = 0 PUB_HASH_INFO = 0 +OLD_PUB_HASH_INFO = 0 HUB = 2 PUB_LOG = 1 PUB_LOG_INFO = 5 @@ -25,18 +27,27 @@ STP = 4 TRM = 7 WCP = 16 +PRECOMPILE_ECRECOVER = 0 PRECOMPILE_ECRECOVER_EFFECTIVE_CALL = 0 -PRECOMPILE_SHA2_BLOCKS = 0 -PRECOMPILE_RIPEMD_BLOCKS = 0 +PRECOMPILE_SHA2 = 0 +PRECOMPILE_SHA2_BLOCKS = 0 +PRECOMPILE_SHA2_EFFECTIVE_CALL = 0 PRECOMPILE_IDENTITY = 0 +PRECOMPILE_MODEXP = 0 PRECOMPILE_MODEXP_EFFECTIVE_CALL = 0 +PRECOMPILE_ECADD = 0 PRECOMPILE_ECADD_EFFECTIVE_CALL = 0 +PRECOMPILE_ECMUL = 0 PRECOMPILE_ECMUL_EFFECTIVE_CALL = 0 +PRECOMPILE_ECPAIRING = 0 PRECOMPILE_ECPAIRING_EFFECTIVE_CALL = 0 PRECOMPILE_ECPAIRING_MILLER_LOOP = 0 -PRECOMPILE_BLAKE2F_ROUNDS = 0 - +PRECOMPILE_BLAKE2F = 0 +PRECOMPILE_BLAKE2F_ROUNDS = 0 +PRECOMPILE_RIPEMD = 0 +PRECOMPILE_RIPEMD_EFFECTIVE_CALL = 0 +PRECOMPILE_RIPEMD_BLOCKS = 0 BLOCK_TX = 0 BLOCK_L2L1LOGS = 0 BLOCK_KECCAK = 0 -BLOCK_L1SIZE = 0 \ No newline at end of file +BLOCK_L1SIZE = 0 diff --git a/zkevm-constraints b/zkevm-constraints index 435746956a..2de36856ee 160000 --- a/zkevm-constraints +++ b/zkevm-constraints @@ -1 +1 @@ -Subproject commit 435746956ad2ec91a50702613fb9261af8c43274 +Subproject commit 2de36856ee71869c3b5121c42ca5f69d37a4f7a0