From df4daf2e53fa367fc0fd051d398a8f87113cc060 Mon Sep 17 00:00:00 2001 From: delehef Date: Wed, 11 Oct 2023 14:40:37 +0200 Subject: [PATCH] feat: implement a reversible state system for modules (#220) Signed-off-by: franklin.delehelle@consensys.net --- .../consensys/linea/zktracer/ZkTracer.java | 8 +- .../zktracer/container/StackedContainer.java | 28 ++ .../container/stacked/list/StackedList.java | 357 ++++++++++++++++++ .../container/stacked/set/StackedSet.java | 171 +++++++++ .../linea/zktracer/module/Module.java | 11 +- .../linea/zktracer/module/add/Add.java | 46 ++- .../zktracer/module/add/AddOperation.java | 21 ++ .../linea/zktracer/module/ext/Ext.java | 24 +- .../linea/zktracer/module/hub/Hub.java | 60 ++- .../linea/zktracer/module/hub/TxInfo.java | 15 +- .../linea/zktracer/module/mod/Mod.java | 24 +- .../linea/zktracer/module/mul/Mul.java | 25 +- .../zktracer/module/rlpAddr/RlpAddr.java | 33 +- .../linea/zktracer/module/rlp_txn/RlpTxn.java | 39 +- .../zktracer/module/rlp_txrcpt/RlpTxrcpt.java | 37 +- .../BitDecOutput.java} | 4 +- .../ByteCountAndPowerOutput.java} | 4 +- .../pattern.java => rlputils/Pattern.java} | 12 +- .../linea/zktracer/module/shf/Shf.java | 17 +- .../linea/zktracer/module/trm/Trm.java | 10 + .../linea/zktracer/module/wcp/Wcp.java | 17 +- .../module/rlp_txrcpt/RandomTxrcptTests.java | 1 + 22 files changed, 854 insertions(+), 110 deletions(-) create mode 100644 src/main/java/net/consensys/linea/zktracer/container/StackedContainer.java create mode 100644 src/main/java/net/consensys/linea/zktracer/container/stacked/list/StackedList.java create mode 100644 src/main/java/net/consensys/linea/zktracer/container/stacked/set/StackedSet.java create mode 100644 src/main/java/net/consensys/linea/zktracer/module/add/AddOperation.java rename src/main/java/net/consensys/linea/zktracer/module/{rlpPatterns/RlpBitDecOutput.java => rlputils/BitDecOutput.java} (90%) rename src/main/java/net/consensys/linea/zktracer/module/{rlpPatterns/RlpByteCountAndPowerOutput.java => rlputils/ByteCountAndPowerOutput.java} (89%) rename src/main/java/net/consensys/linea/zktracer/module/{rlpPatterns/pattern.java => rlputils/Pattern.java} (91%) diff --git a/src/main/java/net/consensys/linea/zktracer/ZkTracer.java b/src/main/java/net/consensys/linea/zktracer/ZkTracer.java index bf4f5835b6..8b947a9eba 100644 --- a/src/main/java/net/consensys/linea/zktracer/ZkTracer.java +++ b/src/main/java/net/consensys/linea/zktracer/ZkTracer.java @@ -118,9 +118,8 @@ public void traceEndTransaction( @Override public void tracePreExecution(final MessageFrame frame) { - this.hub.trace(frame); + this.hub.tracePreOpcode(frame); } - // TODO ADd RlpAddr module in trcaePreExecution @Override public void tracePostExecution(MessageFrame frame, Operation.OperationResult operationResult) { @@ -136,4 +135,9 @@ public void traceContextEnter(MessageFrame frame) { public void traceContextExit(MessageFrame frame) { this.hub.traceContextExit(frame); } + + /** When called, erase all tracing related to the last included transaction. */ + public void popTransaction() { + hub.popTransaction(); + } } diff --git a/src/main/java/net/consensys/linea/zktracer/container/StackedContainer.java b/src/main/java/net/consensys/linea/zktracer/container/StackedContainer.java new file mode 100644 index 0000000000..6bb2fe5abd --- /dev/null +++ b/src/main/java/net/consensys/linea/zktracer/container/StackedContainer.java @@ -0,0 +1,28 @@ +/* + * 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.container; + +/** + * A stacked container must behave as the container it emulates, all the while being able to enter + * nested modification contexts, that can be transparently reverted. + */ +public interface StackedContainer { + /** Enter a new modification context. */ + void enter(); + + /** Erase the modifications brought while in the latest modification context. */ + void pop(); +} diff --git a/src/main/java/net/consensys/linea/zktracer/container/stacked/list/StackedList.java b/src/main/java/net/consensys/linea/zktracer/container/stacked/list/StackedList.java new file mode 100644 index 0000000000..74d1c21870 --- /dev/null +++ b/src/main/java/net/consensys/linea/zktracer/container/stacked/list/StackedList.java @@ -0,0 +1,357 @@ +/* + * 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.container.stacked.list; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.Stack; + +import net.consensys.linea.zktracer.container.StackedContainer; +import org.jetbrains.annotations.NotNull; + +/** + * Implements a system of nested lists behaving as a single on, where the current context + * modification can transparently be dropped. + * + * @param the type of elements stored in the list + */ +public class StackedList implements List, StackedContainer { + private final Stack> lists = new Stack<>(); + + @Override + public void enter() { + this.lists.push(new ArrayList<>()); + } + + @Override + public void pop() { + if (this.lists.isEmpty()) { + throw new RuntimeException("asymmetric pop"); + } + this.lists.pop(); + } + + @Override + public int size() { + return this.lists.stream().mapToInt(List::size).sum(); + } + + @Override + public boolean isEmpty() { + for (List l : this.lists) { + if (!l.isEmpty()) { + return false; + } + } + return true; + } + + @Override + public boolean contains(Object o) { + for (List l : this.lists) { + if (l.contains(o)) { + return true; + } + } + return false; + } + + @NotNull + @Override + public Iterator iterator() { + return new StackedListIterator<>(this); + } + + @NotNull + @Override + public Object[] toArray() { + throw new UnsupportedOperationException("toArray is not supported"); + } + + @NotNull + @Override + public T[] toArray(@NotNull T[] a) { + throw new UnsupportedOperationException("toArray is not supported"); + } + + @Override + public boolean add(E e) { + return this.lists.get(this.lists.size() - 1).add(e); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException("remove not supported"); + } + + @Override + public boolean containsAll(@NotNull Collection c) { + for (var x : c) { + if (!this.contains(x)) { + return false; + } + } + return true; + } + + @Override + public boolean addAll(@NotNull Collection c) { + boolean r = false; + for (var x : c) { + r |= this.add(x); + } + return r; + } + + @Override + public boolean addAll(int index, @NotNull Collection c) { + throw new UnsupportedOperationException("addAll(int) not supported"); + } + + @Override + public boolean removeAll(@NotNull Collection c) { + boolean r = false; + for (var x : c) { + r |= this.remove(x); + } + return r; + } + + @Override + public boolean retainAll(@NotNull Collection c) { + throw new UnsupportedOperationException("retainAll not supported"); + } + + @Override + public void clear() { + this.lists.clear(); + } + + @Override + public E get(int i) { + for (List list : this.lists) { + if (i >= list.size()) { + i -= list.size(); + } else { + return list.get(i); + } + } + return null; + } + + @Override + public E set(int index, E element) { + throw new UnsupportedOperationException("set not supported"); + } + + @Override + public void add(int index, E element) { + throw new UnsupportedOperationException("add(int) not supported"); + } + + @Override + public E remove(int index) { + throw new UnsupportedOperationException("remove not supported"); + } + + @Override + public int indexOf(Object o) { + int i = 0; + for (List l : this.lists) { + final int ii = l.indexOf(o); + if (ii != -1) { + return i + ii; + } + i += l.size(); + } + return -1; + } + + @Override + public int lastIndexOf(Object o) { + throw new UnsupportedOperationException("lastIndexOf not supported"); + } + + @NotNull + @Override + public ListIterator listIterator() { + return new StackedListIterator<>(this); + } + + @NotNull + @Override + public ListIterator listIterator(int index) { + throw new UnsupportedOperationException("listIterator(int) not supported"); + } + + @NotNull + @Override + public List subList(int fromIndex, int toIndex) { + throw new UnsupportedOperationException("subList not supported"); + } + + private static class StackedListIterator implements Iterator, ListIterator { + private final StackedList sl; + /** Position of the iterator in the list of lists */ + private int head = 0; + /** Position of the iterator within the current list, i.e. this.sl.lists[head] */ + private int offset = -1; + + StackedListIterator(StackedList lists) { + this.sl = lists; + } + + private List list() { + return this.sl.lists.get(this.head); + } + + private List list(int i) { + return this.sl.lists.get(i); + } + + F read() { + return this.sl.lists.get(head).get(this.offset); + } + + int toIndex() { + int idx = 0; + for (int i = 0; i < this.head; i++) { + idx += this.list(i).size(); + } + return idx + this.offset; + } + + boolean done() { + return this.head >= this.sl.lists.size() - 1 && this.offset >= this.list().size(); + } + + @Override + public boolean hasNext() { + // First check if the current list is done for + if (offset < this.list().size() - 1) { + return true; + } + // Then check for a next non-empty list + for (int i = this.head + 1; i < this.sl.lists.size(); i++) { + if (!this.list(i).isEmpty()) { + return true; + } + } + // We're empty + return false; + } + + @Override + public F next() { + // If we are not yet at the end of the current list, return the natural next element + if (offset < this.list().size() - 1) { + this.offset++; + return this.read(); + } + + this.head++; + // Otherwise, jump to the next non-empty list if we can + for (int i = head; i < this.sl.lists.size(); i++) { + if (!this.list(i).isEmpty()) { + this.head = i; + this.offset = 0; + return this.read(); + } + } + + this.head = this.sl.lists.size() - 1; + this.offset = this.list().size() - 1; + throw new NoSuchElementException(); + } + + @Override + public boolean hasPrevious() { + if (offset > 0) { + return true; + } + + if (head > 0) { + for (int i = head - 1; i >= 0; i--) { + if (!this.list(i).isEmpty()) { + return true; + } + } + } + + return false; + } + + @Override + public F previous() { + // If we are not yet at the very beginning of the current list, return the natural previous + // element + if (offset > 0) { + this.offset--; + return this.read(); + } + + // Otherwise, jump to the previous non-empty list if we can + for (int i = head - 1; i >= 0; i--) { + if (!this.list(i).isEmpty()) { + this.head = i; + this.offset = this.list().size() - 1; + return this.read(); + } + } + + this.head = 0; + this.offset = 0; + return null; + } + + @Override + public int nextIndex() { + final int idx = this.toIndex(); + if (this.done()) { + return idx; + } + return idx + 1; + } + + @Override + public int previousIndex() { + final int idx = this.toIndex(); + if (idx > 0) { + return idx - 1; + } + return 0; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove not supported"); + } + + @Override + public void set(F e) { + this.sl.lists.get(head).set(this.offset, e); + } + + @Override + public void add(F f) { + throw new UnsupportedOperationException("add not supported"); + } + } +} diff --git a/src/main/java/net/consensys/linea/zktracer/container/stacked/set/StackedSet.java b/src/main/java/net/consensys/linea/zktracer/container/stacked/set/StackedSet.java new file mode 100644 index 0000000000..34bd4eab57 --- /dev/null +++ b/src/main/java/net/consensys/linea/zktracer/container/stacked/set/StackedSet.java @@ -0,0 +1,171 @@ +/* + * 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.container.stacked.set; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Stack; + +import net.consensys.linea.zktracer.container.StackedContainer; +import org.jetbrains.annotations.NotNull; + +/** + * Implements a system of nested sets behaving as a single on, where the current context + * modification can transparently be dropped. + * + * @param the type of elements stored in the set + */ +public class StackedSet implements StackedContainer, java.util.Set { + private final Stack> sets = new Stack<>(); + + @Override + public void enter() { + this.sets.push(new HashSet<>()); + } + + @Override + public void pop() { + this.sets.pop(); + } + + @Override + public int size() { + return this.sets.stream().mapToInt(Set::size).sum(); + } + + @Override + public boolean isEmpty() { + for (Set set : this.sets) { + if (!set.isEmpty()) { + return false; + } + } + + return true; + } + + @Override + public boolean contains(Object o) { + for (Set set : this.sets) { + if (set.contains(o)) { + return true; + } + } + return false; + } + + @NotNull + @Override + public Iterator iterator() { + return new StackedSetIterator<>(this.sets); + } + + @NotNull + @Override + public Object[] toArray() { + throw new UnsupportedOperationException("toArray not supported"); + } + + @NotNull + @Override + public T[] toArray(@NotNull T[] a) { + throw new UnsupportedOperationException("toArray not supported"); + } + + @Override + public boolean add(E e) { + // An element should *never* be duplicated, for it would appear twice in the iterator. + if (this.contains(e)) { + return false; + } + + return this.sets.peek().add(e); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException("remove not supported"); + } + + @Override + public boolean containsAll(@NotNull Collection c) { + for (var x : c) { + if (!this.contains(x)) { + return false; + } + } + return true; + } + + @Override + public boolean addAll(@NotNull Collection c) { + boolean r = false; + for (var x : c) { + r |= this.sets.peek().add(x); + } + return r; + } + + @Override + public boolean retainAll(@NotNull Collection c) { + throw new UnsupportedOperationException("retainAll not supported"); + } + + @Override + public boolean removeAll(@NotNull Collection c) { + throw new UnsupportedOperationException("removeAll not supported"); + } + + @Override + public void clear() { + this.sets.clear(); + } + + /** This class acts as an {@link Iterator} over a StackedSet. */ + private static class StackedSetIterator implements Iterator { + private final List> iters = new ArrayList<>(); + + StackedSetIterator(List> sets) { + for (Set set : sets) { + this.iters.add(set.iterator()); + } + } + + @Override + public boolean hasNext() { + for (Iterator iter : iters) { + if (iter.hasNext()) { + return true; + } + } + return false; + } + + @Override + public E next() { + for (Iterator iter : iters) { + if (iter.hasNext()) { + return iter.next(); + } + } + return null; + } + } +} diff --git a/src/main/java/net/consensys/linea/zktracer/module/Module.java b/src/main/java/net/consensys/linea/zktracer/module/Module.java index fc91d45ef2..7065b5d97e 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/Module.java +++ b/src/main/java/net/consensys/linea/zktracer/module/Module.java @@ -50,7 +50,16 @@ default void traceContextEnter(MessageFrame frame) {} default void traceContextExit(MessageFrame frame) {} - default void trace(MessageFrame frame) {} + default void tracePreOpcode(MessageFrame frame) {} + + /** + * Called at the eve of a new transaction; intended to create a new modification context for the + * stacked state of the module. + */ + void enterTransaction(); + + /** Called when a transaction execution is cancelled; should revert the state of the module. */ + void popTransaction(); int lineCount(); diff --git a/src/main/java/net/consensys/linea/zktracer/module/add/Add.java b/src/main/java/net/consensys/linea/zktracer/module/add/Add.java index 35f85a694e..76ebd55455 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/add/Add.java +++ b/src/main/java/net/consensys/linea/zktracer/module/add/Add.java @@ -16,12 +16,11 @@ package net.consensys.linea.zktracer.module.add; import java.math.BigInteger; -import java.util.HashMap; -import java.util.Map; import net.consensys.linea.zktracer.bytes.Bytes16; import net.consensys.linea.zktracer.bytes.UnsignedByte; import net.consensys.linea.zktracer.bytestheta.BaseBytes; +import net.consensys.linea.zktracer.container.stacked.set.StackedSet; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.opcode.OpCode; import net.consensys.linea.zktracer.opcode.OpCodeData; @@ -32,28 +31,36 @@ /** Implementation of a {@link Module} for addition/subtraction. */ public class Add implements Module { - public static final String ADD_JSON_KEY = "add"; + private static final UInt256 TWO_TO_THE_128 = UInt256.ONE.shiftLeft(128); + private int stamp = 0; final Trace.TraceBuilder trace = Trace.builder(); - private final UInt256 twoToThe128 = UInt256.ONE.shiftLeft(128); - /** A set of the operations to trace */ - private final Map> chunks = new HashMap<>(); + private final StackedSet chunks = new StackedSet<>(); @Override public String jsonKey() { - return ADD_JSON_KEY; + return "add"; + } + + @Override + public void enterTransaction() { + this.chunks.enter(); } @Override - public void trace(MessageFrame frame) { + public void popTransaction() { + this.chunks.pop(); + } + + @Override + public void tracePreOpcode(MessageFrame frame) { final Bytes32 arg1 = Bytes32.leftPad(frame.getStackItem(0)); final Bytes32 arg2 = Bytes32.leftPad(frame.getStackItem(1)); - this.chunks - .computeIfAbsent(OpCode.of(frame.getCurrentOperation().getOpcode()), x -> new HashMap<>()) - .put(arg1, arg2); + this.chunks.add( + new AddOperation(OpCode.of(frame.getCurrentOperation().getOpcode()), arg1, arg2)); } /** @@ -125,7 +132,7 @@ private void traceAddOperation(OpCode opCode, Bytes32 arg1, Bytes32 arg2) { addRes = Bytes32.wrap((UInt256.fromBytes(resLo)).add(UInt256.fromBytes(arg2Lo))); } - overflowLo = (addRes.compareTo(twoToThe128) >= 0); + overflowLo = (addRes.compareTo(TWO_TO_THE_128) >= 0); trace .acc1(resHi.slice(0, 1 + i).toUnsignedBigInteger()) @@ -148,11 +155,8 @@ private void traceAddOperation(OpCode opCode, Bytes32 arg1, Bytes32 arg2) { @Override public Object commit() { - for (Map.Entry> op : this.chunks.entrySet()) { - OpCode opCode = op.getKey(); - for (Map.Entry args : op.getValue().entrySet()) { - this.traceAddOperation(opCode, args.getKey(), args.getValue()); - } + for (AddOperation op : this.chunks) { + this.traceAddOperation(op.opCodem(), op.arg1(), op.arg2()); } return new AddTrace(trace.build()); @@ -160,12 +164,6 @@ public Object commit() { @Override public int lineCount() { - int r = 0; - for (Map.Entry> op : this.chunks.entrySet()) { - for (Map.Entry ignored : op.getValue().entrySet()) { - r += 16; - } - } - return r; + return this.chunks.size() * 16; } } diff --git a/src/main/java/net/consensys/linea/zktracer/module/add/AddOperation.java b/src/main/java/net/consensys/linea/zktracer/module/add/AddOperation.java new file mode 100644 index 0000000000..6a40ae407c --- /dev/null +++ b/src/main/java/net/consensys/linea/zktracer/module/add/AddOperation.java @@ -0,0 +1,21 @@ +/* + * 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.add; + +import net.consensys.linea.zktracer.opcode.OpCode; +import org.apache.tuweni.bytes.Bytes32; + +public record AddOperation(OpCode opCodem, Bytes32 arg1, Bytes32 arg2) {} diff --git a/src/main/java/net/consensys/linea/zktracer/module/ext/Ext.java b/src/main/java/net/consensys/linea/zktracer/module/ext/Ext.java index c31063ada0..4fe014188d 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/ext/Ext.java +++ b/src/main/java/net/consensys/linea/zktracer/module/ext/Ext.java @@ -16,22 +16,23 @@ package net.consensys.linea.zktracer.module.ext; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.set.StackedSet; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.opcode.OpCodeData; import net.consensys.linea.zktracer.opcode.OpCodes; import org.apache.tuweni.bytes.Bytes32; +import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.worldstate.WorldView; public class Ext implements Module { final Trace.TraceBuilder trace = Trace.builder(); private int stamp = 0; /** A set of the operations to trace */ - private final Set operations = new HashSet<>(); + private final StackedSet operations = new StackedSet<>(); @Override public String jsonKey() { @@ -39,7 +40,22 @@ public String jsonKey() { } @Override - public void trace(final MessageFrame frame) { + public void traceStartTx(WorldView worldView, Transaction tx) { + this.operations.enter(); + } + + @Override + public void enterTransaction() { + this.operations.enter(); + } + + @Override + public void popTransaction() { + this.operations.pop(); + } + + @Override + public void tracePreOpcode(final MessageFrame frame) { final OpCodeData opCode = OpCodes.of(frame.getCurrentOperation().getOpcode()); final Bytes32 arg1 = Bytes32.wrap(frame.getStackItem(0)); final Bytes32 arg2 = Bytes32.wrap(frame.getStackItem(1)); diff --git a/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java b/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java index 1f2cba4440..b6490ea42d 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java +++ b/src/main/java/net/consensys/linea/zktracer/module/hub/Hub.java @@ -27,6 +27,7 @@ import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; import net.consensys.linea.zktracer.EWord; +import net.consensys.linea.zktracer.container.stacked.list.StackedList; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.module.add.Add; import net.consensys.linea.zktracer.module.ext.Ext; @@ -93,7 +94,7 @@ public class Hub implements Module { public final Trace.TraceBuilder trace = Trace.builder(); // Tx -> Opcode -> TraceSection - private final List traceSections = new ArrayList<>(); + private final StackedList traceSections = new StackedList<>(); @Getter ConflationInfo conflation = new ConflationInfo(); @Getter BlockInfo block = new BlockInfo(); @@ -103,6 +104,7 @@ public class Hub implements Module { private final DeferRegistry defers = new DeferRegistry(); @Getter private Exceptions exceptions; @Getter int stamp = 0; + private int preTxStamp; public OpCodeData opCodeData() { return this.currentFrame().opCode().getData(); @@ -154,8 +156,21 @@ void createNewTxTrace() { private final RlpTxn rlpTxn = new RlpTxn(); private final RlpTxrcpt rlpTxrcpt = new RlpTxrcpt(); private final RlpAddr rlpAddr = new RlpAddr(); - - public Hub() {} + private final List modules; + + public Hub() { + this.modules = + List.of( + this.add, + this.ext, + this.mod, + this.mul, + this.shf, + this.wcp, + this.rlpTxn, + this.rlpTxrcpt, + this.rlpAddr); + } /** * @return the list of modules that need to be triggered in a self-standing way by the {@link @@ -361,33 +376,33 @@ void triggerModules(MessageFrame frame) { switch (this.opCodeData().instructionFamily()) { case ADD -> { if (this.exceptions.noStackException()) { - this.add.trace(frame); + this.add.tracePreOpcode(frame); } } case MOD -> { if (this.exceptions.noStackException()) { - this.mod.trace(frame); + this.mod.tracePreOpcode(frame); } } case MUL -> { if (this.exceptions.noStackException()) { - this.mul.trace(frame); + this.mul.tracePreOpcode(frame); } } case EXT -> { if (this.exceptions.noStackException()) { - this.ext.trace(frame); + this.ext.tracePreOpcode(frame); } } case WCP -> { if (this.exceptions.noStackException()) { - this.wcp.trace(frame); + this.wcp.tracePreOpcode(frame); } } case BIN -> {} case SHF -> { if (this.exceptions.noStackException()) { - this.shf.trace(frame); + this.shf.tracePreOpcode(frame); } } case KEC -> {} @@ -413,7 +428,7 @@ void triggerModules(MessageFrame frame) { .getBalance() .toUInt256() .greaterOrEqualThan(value)) { - this.rlpAddr.trace(frame); + this.rlpAddr.tracePreOpcode(frame); } } } @@ -514,8 +529,21 @@ public static Address effectiveToAddress(Transaction tx) { .orElse(Address.contractAddress(tx.getSender(), tx.getNonce())); } + @Override + public void enterTransaction() { + this.preTxStamp = this.stamp; + this.tx.enter(); + this.traceSections.enter(); + + for (Module m : this.modules) { + m.enterTransaction(); + } + } + @Override public void traceStartTx(final WorldView world, final Transaction tx) { + this.enterTransaction(); + this.exceptions = Exceptions.empty(); this.rlpAddr.traceStartTx(world, tx); @@ -534,6 +562,16 @@ public void traceStartTx(final WorldView world, final Transaction tx) { this.processStateInit(world); } + @Override + public void popTransaction() { + this.stamp = this.preTxStamp; + this.tx.pop(); + this.traceSections.pop(); + for (Module m : this.modules) { + m.popTransaction(); + } + } + @Override public void traceEndTx( WorldView world, Transaction tx, boolean status, Bytes output, List logs, long gasUsed) { @@ -617,7 +655,7 @@ public void traceContextExit(MessageFrame frame) { } @Override - public void trace(final MessageFrame frame) { + public void tracePreOpcode(final MessageFrame frame) { if (this.tx.state() == TxState.TX_SKIP) { return; } diff --git a/src/main/java/net/consensys/linea/zktracer/module/hub/TxInfo.java b/src/main/java/net/consensys/linea/zktracer/module/hub/TxInfo.java index e2c6eb7d2c..85295612ef 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/hub/TxInfo.java +++ b/src/main/java/net/consensys/linea/zktracer/module/hub/TxInfo.java @@ -21,6 +21,7 @@ import lombok.Setter; import lombok.experimental.Accessors; import net.consensys.linea.zktracer.ZkTracer; +import net.consensys.linea.zktracer.container.StackedContainer; import org.hyperledger.besu.datatypes.Quantity; import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.datatypes.Wei; @@ -30,9 +31,11 @@ /** Stores transaction-specific information. */ @Accessors(fluent = true) @Getter -public class TxInfo { +public class TxInfo implements StackedContainer { private static final GasCalculator gc = ZkTracer.gasCalculator; + private int preExecNumber = 0; + private int number = 0; private Transaction transaction; @Setter private TxState state; @@ -90,4 +93,14 @@ void update(final Transaction tx) { this.transaction = tx; this.initialGas = tx.getGasLimit(); } + + @Override + public void enter() { + this.preExecNumber = this.number; + } + + @Override + public void pop() { + this.number = this.preExecNumber; + } } diff --git a/src/main/java/net/consensys/linea/zktracer/module/mod/Mod.java b/src/main/java/net/consensys/linea/zktracer/module/mod/Mod.java index d8b608f30c..c8c9cb4fb7 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/mod/Mod.java +++ b/src/main/java/net/consensys/linea/zktracer/module/mod/Mod.java @@ -16,17 +16,18 @@ package net.consensys.linea.zktracer.module.mod; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.set.StackedSet; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.opcode.OpCode; import net.consensys.linea.zktracer.opcode.OpCodeData; import net.consensys.linea.zktracer.opcode.OpCodes; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; +import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.worldstate.WorldView; public class Mod implements Module { private int stamp = 0; @@ -38,10 +39,10 @@ public String jsonKey() { return "mod"; } - private final Set chunks = new HashSet<>(); + private final StackedSet chunks = new StackedSet<>(); @Override - public void trace(final MessageFrame frame) { + public void tracePreOpcode(final MessageFrame frame) { final OpCodeData opCodeData = OpCodes.of(frame.getCurrentOperation().getOpcode()); final Bytes32 arg1 = Bytes32.leftPad(frame.getStackItem(0)); final Bytes32 arg2 = Bytes32.leftPad(frame.getStackItem(1)); @@ -49,6 +50,21 @@ public void trace(final MessageFrame frame) { this.chunks.add(new ModOperation(opCodeData, arg1, arg2)); } + @Override + public void enterTransaction() { + this.chunks.enter(); + } + + @Override + public void popTransaction() { + this.chunks.pop(); + } + + @Override + public void traceStartTx(WorldView worldView, Transaction tx) { + this.chunks.enter(); + } + public void traceModOperation(ModOperation op) { this.stamp++; diff --git a/src/main/java/net/consensys/linea/zktracer/module/mul/Mul.java b/src/main/java/net/consensys/linea/zktracer/module/mul/Mul.java index e8d39f1f53..4407c415ae 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/mul/Mul.java +++ b/src/main/java/net/consensys/linea/zktracer/module/mul/Mul.java @@ -16,20 +16,21 @@ package net.consensys.linea.zktracer.module.mul; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.set.StackedSet; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.opcode.OpCode; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; +import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.worldstate.WorldView; public class Mul implements Module { final Trace.TraceBuilder trace = Trace.builder(); /** A set of the operations to trace */ - private final Set operations = new HashSet<>(); + private final StackedSet operations = new StackedSet<>(); private int stamp = 0; @@ -38,9 +39,8 @@ public String jsonKey() { return "mul"; } - @SuppressWarnings("UnusedVariable") @Override - public void trace(MessageFrame frame) { + public void tracePreOpcode(MessageFrame frame) { final OpCode opCode = OpCode.of(frame.getCurrentOperation().getOpcode()); final Bytes32 arg1 = Bytes32.leftPad(frame.getStackItem(0)); final Bytes32 arg2 = Bytes32.leftPad(frame.getStackItem(1)); @@ -48,6 +48,21 @@ public void trace(MessageFrame frame) { operations.add(new MulOperation(opCode, arg1, arg2)); } + @Override + public void enterTransaction() { + this.operations.enter(); + } + + @Override + public void popTransaction() { + this.operations.pop(); + } + + @Override + public void traceStartTx(WorldView worldView, Transaction tx) { + this.operations.enter(); + } + @Override public Object commit() { for (var op : this.operations) { diff --git a/src/main/java/net/consensys/linea/zktracer/module/rlpAddr/RlpAddr.java b/src/main/java/net/consensys/linea/zktracer/module/rlpAddr/RlpAddr.java index bcdc7dd755..e30dfed096 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/rlpAddr/RlpAddr.java +++ b/src/main/java/net/consensys/linea/zktracer/module/rlpAddr/RlpAddr.java @@ -16,21 +16,20 @@ package net.consensys.linea.zktracer.module.rlpAddr; import static net.consensys.linea.zktracer.bytes.conversions.bigIntegerToBytes; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.bitDecomposition; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.byteCounting; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.padToGivenSizeWithLeftZero; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.padToGivenSizeWithRightZero; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.bitDecomposition; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.byteCounting; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.padToGivenSizeWithLeftZero; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.padToGivenSizeWithRightZero; import static org.hyperledger.besu.crypto.Hash.keccak256; import static org.hyperledger.besu.evm.internal.Words.clampedToLong; import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.list.StackedList; import net.consensys.linea.zktracer.module.Module; -import net.consensys.linea.zktracer.module.rlpPatterns.RlpBitDecOutput; -import net.consensys.linea.zktracer.module.rlpPatterns.RlpByteCountAndPowerOutput; +import net.consensys.linea.zktracer.module.rlputils.BitDecOutput; +import net.consensys.linea.zktracer.module.rlputils.ByteCountAndPowerOutput; import net.consensys.linea.zktracer.opcode.OpCode; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -46,13 +45,23 @@ public class RlpAddr implements Module { private static final int LLARGE = 16; private final Trace.TraceBuilder builder = Trace.builder(); - private final List chunkList = new ArrayList<>(); + private final StackedList chunkList = new StackedList<>(); @Override public String jsonKey() { return "rlpAddr"; } + @Override + public void enterTransaction() { + this.chunkList.enter(); + } + + @Override + public void popTransaction() { + this.chunkList.pop(); + } + @Override public void traceStartTx(WorldView world, Transaction tx) { if (tx.getTo().isEmpty()) { @@ -62,7 +71,7 @@ public void traceStartTx(WorldView world, Transaction tx) { } @Override - public void trace(MessageFrame frame) { + public void tracePreOpcode(MessageFrame frame) { OpCode opcode = OpCode.of(frame.getCurrentOperation().getOpcode()); if (opcode.equals(OpCode.CREATE)) { RlpAddrChunk chunk = @@ -158,11 +167,11 @@ private void traceCreate(int stamp, BigInteger nonce, Address addr) { if (nonce.equals(BigInteger.ZERO)) { nonceByteSize = 0; } - RlpByteCountAndPowerOutput byteCounting = byteCounting(nonceByteSize, RECIPE1_CT_MAX); + ByteCountAndPowerOutput byteCounting = byteCounting(nonceByteSize, RECIPE1_CT_MAX); // Compute the bit decomposition of the last input's byte final byte lastByte = nonceShifted.get(RECIPE1_CT_MAX - 1); - RlpBitDecOutput bitDecomposition = bitDecomposition(0xff & lastByte, RECIPE1_CT_MAX); + BitDecOutput bitDecomposition = bitDecomposition(0xff & lastByte, RECIPE1_CT_MAX); int size_rlp_nonce = nonceByteSize; if (!tinyNonZeroNonce) { diff --git a/src/main/java/net/consensys/linea/zktracer/module/rlp_txn/RlpTxn.java b/src/main/java/net/consensys/linea/zktracer/module/rlp_txn/RlpTxn.java index 6d90add8ff..fdd5999d9f 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/rlp_txn/RlpTxn.java +++ b/src/main/java/net/consensys/linea/zktracer/module/rlp_txn/RlpTxn.java @@ -16,11 +16,11 @@ package net.consensys.linea.zktracer.module.rlp_txn; import static net.consensys.linea.zktracer.bytes.conversions.bigIntegerToBytes; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.bitDecomposition; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.byteCounting; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.outerRlpSize; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.padToGivenSizeWithLeftZero; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.padToGivenSizeWithRightZero; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.bitDecomposition; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.byteCounting; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.outerRlpSize; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.padToGivenSizeWithLeftZero; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.padToGivenSizeWithRightZero; import static org.hyperledger.besu.ethereum.core.encoding.EncodingContext.BLOCK_BODY; import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.encodeOpaqueBytes; @@ -32,9 +32,10 @@ import com.google.common.base.Preconditions; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.list.StackedList; import net.consensys.linea.zktracer.module.Module; -import net.consensys.linea.zktracer.module.rlpPatterns.RlpBitDecOutput; -import net.consensys.linea.zktracer.module.rlpPatterns.RlpByteCountAndPowerOutput; +import net.consensys.linea.zktracer.module.rlputils.BitDecOutput; +import net.consensys.linea.zktracer.module.rlputils.ByteCountAndPowerOutput; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt256; @@ -68,7 +69,7 @@ public class RlpTxn implements Module { public static final int intPrefixLongList = bytesPrefixLongList.toUnsignedBigInteger().intValueExact(); - private final List chunkList = new ArrayList<>(); + private final StackedList chunkList = new StackedList<>(); // Used to check the reconstruction of RLPs Bytes reconstructedRlpLt; @@ -79,6 +80,16 @@ public String jsonKey() { return "rlpTxn"; } + @Override + public void enterTransaction() { + this.chunkList.enter(); + } + + @Override + public void popTransaction() { + this.chunkList.pop(); + } + @Override public void traceStartTx(WorldView worldView, Transaction tx) { boolean requiresEvmExecution; @@ -562,7 +573,7 @@ private void rlpByteString( RlpTxnColumnsValue traceValue) { int lengthSize = bigIntegerToBytes(BigInteger.valueOf(length)).size(); - RlpByteCountAndPowerOutput byteCountingOutput = byteCounting(lengthSize, 8); + ByteCountAndPowerOutput byteCountingOutput = byteCounting(lengthSize, 8); traceValue.partialReset(phase, 8, lt, lx); traceValue.INPUT_1 = bigIntegerToBytes(BigInteger.valueOf(length)); @@ -644,10 +655,10 @@ private void rlpInt( Bytes inputByte = bigIntegerToBytes(input); int inputSize = inputByte.size(); - RlpByteCountAndPowerOutput byteCountingOutput = byteCounting(inputSize, nStep); + ByteCountAndPowerOutput byteCountingOutput = byteCounting(inputSize, nStep); Bytes inputBytePadded = padToGivenSizeWithLeftZero(inputByte, nStep); - RlpBitDecOutput bitDecOutput = + BitDecOutput bitDecOutput = bitDecomposition(0xff & inputBytePadded.get(inputBytePadded.size() - 1), nStep); traceValue.INPUT_1 = inputByte; @@ -697,10 +708,10 @@ private void handle32BytesInteger(RlpTxnColumnsValue traceValue, int phase, BigI traceValue.INPUT_1 = inputByte32.slice(0, llarge); traceValue.INPUT_2 = inputByte32.slice(llarge, llarge); - RlpByteCountAndPowerOutput byteCounting; + ByteCountAndPowerOutput byteCounting; if (inputLen <= traceValue.nSTEP) { - RlpByteCountAndPowerOutput byteCountingOutput = byteCounting(inputLen, traceValue.nSTEP); - RlpBitDecOutput bitDecOutput = + ByteCountAndPowerOutput byteCountingOutput = byteCounting(inputLen, traceValue.nSTEP); + BitDecOutput bitDecOutput = bitDecomposition(inputByte.get(inputByte.size() - 1), traceValue.nSTEP); for (int ct = 0; ct < traceValue.nSTEP; ct++) { diff --git a/src/main/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RlpTxrcpt.java b/src/main/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RlpTxrcpt.java index 8ddd7a2e8f..71bcf3b688 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RlpTxrcpt.java +++ b/src/main/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RlpTxrcpt.java @@ -16,22 +16,22 @@ package net.consensys.linea.zktracer.module.rlp_txrcpt; import static net.consensys.linea.zktracer.bytes.conversions.bigIntegerToBytes; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.bitDecomposition; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.byteCounting; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.outerRlpSize; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.padToGivenSizeWithLeftZero; -import static net.consensys.linea.zktracer.module.rlpPatterns.pattern.padToGivenSizeWithRightZero; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.bitDecomposition; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.byteCounting; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.outerRlpSize; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.padToGivenSizeWithLeftZero; +import static net.consensys.linea.zktracer.module.rlputils.Pattern.padToGivenSizeWithRightZero; import java.math.BigInteger; -import java.util.ArrayList; import java.util.List; import java.util.function.Function; import com.google.common.base.Preconditions; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.list.StackedList; import net.consensys.linea.zktracer.module.Module; -import net.consensys.linea.zktracer.module.rlpPatterns.RlpBitDecOutput; -import net.consensys.linea.zktracer.module.rlpPatterns.RlpByteCountAndPowerOutput; +import net.consensys.linea.zktracer.module.rlputils.BitDecOutput; +import net.consensys.linea.zktracer.module.rlputils.ByteCountAndPowerOutput; import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.datatypes.TransactionType; @@ -53,13 +53,23 @@ public class RlpTxrcpt implements Module { private int absLogNumMax = 0; private int absLogNum = 0; private final Trace.TraceBuilder builder = Trace.builder(); - List chunkList = new ArrayList<>(); + StackedList chunkList = new StackedList<>(); @Override public String jsonKey() { return "rlpTxRcpt"; } + @Override + public void enterTransaction() { + this.chunkList.enter(); + } + + @Override + public void popTransaction() { + this.chunkList.pop(); + } + @Override public void traceEndTx( WorldView worldView, @@ -360,7 +370,7 @@ private void phase4(RlpTxrcptColumns traceValue, List logList) { // In INPUT_2 is stored the number of topics, stored in INDEX_LOCAL at the previous // row this.builder.setInput2Relative(BigInteger.valueOf(indexLocalEndTopic), k); - // In Input_1 is the Datasize, and in Input_3 the only byte of Data + // In Input_1 is the data size, and in Input_3 the only byte of Data this.builder.setInput1Relative(BigInteger.ONE, k); this.builder.setInput3Relative(logList.get(i).getData().toUnsignedBigInteger(), k); } @@ -442,7 +452,7 @@ private void rlpByteString( Bytes.ofUnsignedLong(length).size() - Bytes.ofUnsignedLong(length).numberOfLeadingZeroBytes(); - RlpByteCountAndPowerOutput byteCountingOutput = byteCounting(lengthSize, 8); + ByteCountAndPowerOutput byteCountingOutput = byteCounting(lengthSize, 8); traceValue.partialReset(phase, 8); traceValue.input1 = bigIntegerToBytes(BigInteger.valueOf(length)); @@ -525,11 +535,10 @@ private void rlpInt( traceValue.input1 = bigIntegerToBytes(BigInteger.valueOf(input)); int inputSize = traceValue.input1.size(); - RlpByteCountAndPowerOutput byteCountingOutput = byteCounting(inputSize, 8); + ByteCountAndPowerOutput byteCountingOutput = byteCounting(inputSize, 8); Bytes inputBytes = padToGivenSizeWithLeftZero(traceValue.input1, 8); - RlpBitDecOutput bitDecOutput = - bitDecomposition(0xff & inputBytes.get(inputBytes.size() - 1), 8); + BitDecOutput bitDecOutput = bitDecomposition(0xff & inputBytes.get(inputBytes.size() - 1), 8); for (int ct = 0; ct < 8; ct++) { traceValue.counter = ct; diff --git a/src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/RlpBitDecOutput.java b/src/main/java/net/consensys/linea/zktracer/module/rlputils/BitDecOutput.java similarity index 90% rename from src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/RlpBitDecOutput.java rename to src/main/java/net/consensys/linea/zktracer/module/rlputils/BitDecOutput.java index 19ed1e978c..a897cd501c 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/RlpBitDecOutput.java +++ b/src/main/java/net/consensys/linea/zktracer/module/rlputils/BitDecOutput.java @@ -13,7 +13,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package net.consensys.linea.zktracer.module.rlpPatterns; +package net.consensys.linea.zktracer.module.rlputils; import java.util.ArrayList; import java.util.List; @@ -21,7 +21,7 @@ import lombok.Getter; @Getter -public class RlpBitDecOutput { +public class BitDecOutput { @Getter private List bitDecList = new ArrayList<>(); @Getter private List bitAccList = new ArrayList<>(); } diff --git a/src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/RlpByteCountAndPowerOutput.java b/src/main/java/net/consensys/linea/zktracer/module/rlputils/ByteCountAndPowerOutput.java similarity index 89% rename from src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/RlpByteCountAndPowerOutput.java rename to src/main/java/net/consensys/linea/zktracer/module/rlputils/ByteCountAndPowerOutput.java index eee93c85be..a2bb8a2f75 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/RlpByteCountAndPowerOutput.java +++ b/src/main/java/net/consensys/linea/zktracer/module/rlputils/ByteCountAndPowerOutput.java @@ -13,7 +13,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package net.consensys.linea.zktracer.module.rlpPatterns; +package net.consensys.linea.zktracer.module.rlputils; import java.math.BigInteger; import java.util.ArrayList; @@ -21,7 +21,7 @@ import lombok.Getter; -public class RlpByteCountAndPowerOutput { +public class ByteCountAndPowerOutput { @Getter private List powerList = new ArrayList<>(); @Getter private List accByteSizeList = new ArrayList<>(); } diff --git a/src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/pattern.java b/src/main/java/net/consensys/linea/zktracer/module/rlputils/Pattern.java similarity index 91% rename from src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/pattern.java rename to src/main/java/net/consensys/linea/zktracer/module/rlputils/Pattern.java index 02c8c7422a..6c7b33b9f3 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/rlpPatterns/pattern.java +++ b/src/main/java/net/consensys/linea/zktracer/module/rlputils/Pattern.java @@ -13,14 +13,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package net.consensys.linea.zktracer.module.rlpPatterns; +package net.consensys.linea.zktracer.module.rlputils; import java.math.BigInteger; import com.google.common.base.Preconditions; import org.apache.tuweni.bytes.Bytes; -public class pattern { +public class Pattern { /** * Returns the size of RLP(something) where something is of size inputSize (!=1) (it can be ZERO * though). @@ -70,8 +70,8 @@ public static Bytes padToGivenSizeWithRightZero(Bytes input, int wantedSize) { * @param nbStep * @return */ - public static RlpByteCountAndPowerOutput byteCounting(int inputByteLen, int nbStep) { - RlpByteCountAndPowerOutput output = new RlpByteCountAndPowerOutput(); + public static ByteCountAndPowerOutput byteCounting(int inputByteLen, int nbStep) { + ByteCountAndPowerOutput output = new ByteCountAndPowerOutput(); BigInteger power; int accByteSize = 0; @@ -107,10 +107,10 @@ public static RlpByteCountAndPowerOutput byteCounting(int inputByteLen, int nbSt * @param nbStep * @return */ - public static RlpBitDecOutput bitDecomposition(int input, int nbStep) { + public static BitDecOutput bitDecomposition(int input, int nbStep) { Preconditions.checkArgument(nbStep >= 8, "Number of steps must be at least 8"); - RlpBitDecOutput output = new RlpBitDecOutput(); + BitDecOutput output = new BitDecOutput(); // Set to zero first value for (int i = 0; i < nbStep; i++) { output.getBitAccList().add(i, 0); diff --git a/src/main/java/net/consensys/linea/zktracer/module/shf/Shf.java b/src/main/java/net/consensys/linea/zktracer/module/shf/Shf.java index 8bf7cc6e0b..7d5dbcb4e7 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/shf/Shf.java +++ b/src/main/java/net/consensys/linea/zktracer/module/shf/Shf.java @@ -16,10 +16,9 @@ package net.consensys.linea.zktracer.module.shf; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.set.StackedSet; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.opcode.OpCode; import org.apache.tuweni.bytes.Bytes32; @@ -28,7 +27,7 @@ public class Shf implements Module { final Trace.TraceBuilder trace = Trace.builder(); private int stamp = 0; - private final Set operations = new HashSet<>(); + private final StackedSet operations = new StackedSet<>(); @Override public String jsonKey() { @@ -36,7 +35,17 @@ public String jsonKey() { } @Override - public void trace(MessageFrame frame) { + public void enterTransaction() { + this.operations.enter(); + } + + @Override + public void popTransaction() { + this.operations.pop(); + } + + @Override + public void tracePreOpcode(MessageFrame frame) { final Bytes32 arg1 = Bytes32.wrap(frame.getStackItem(0)); final Bytes32 arg2 = Bytes32.wrap(frame.getStackItem(1)); this.operations.add( diff --git a/src/main/java/net/consensys/linea/zktracer/module/trm/Trm.java b/src/main/java/net/consensys/linea/zktracer/module/trm/Trm.java index 3ef2c5c0f5..a6c0c3e29f 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/trm/Trm.java +++ b/src/main/java/net/consensys/linea/zktracer/module/trm/Trm.java @@ -23,6 +23,16 @@ public String jsonKey() { return "trm"; } + @Override + public void enterTransaction() { + // TODO: + } + + @Override + public void popTransaction() { + // TODO: + } + @Override public Object commit() { return null; diff --git a/src/main/java/net/consensys/linea/zktracer/module/wcp/Wcp.java b/src/main/java/net/consensys/linea/zktracer/module/wcp/Wcp.java index 58dada694b..3596dc1c3b 100644 --- a/src/main/java/net/consensys/linea/zktracer/module/wcp/Wcp.java +++ b/src/main/java/net/consensys/linea/zktracer/module/wcp/Wcp.java @@ -16,10 +16,9 @@ package net.consensys.linea.zktracer.module.wcp; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; import net.consensys.linea.zktracer.bytes.UnsignedByte; +import net.consensys.linea.zktracer.container.stacked.set.StackedSet; import net.consensys.linea.zktracer.module.Module; import net.consensys.linea.zktracer.opcode.OpCode; import net.consensys.linea.zktracer.opcode.OpCodeData; @@ -29,7 +28,7 @@ public class Wcp implements Module { final Trace.TraceBuilder builder = Trace.builder(); - private final Set operations = new HashSet<>(); + private final StackedSet operations = new StackedSet<>(); private int stamp = 0; @Override @@ -38,7 +37,17 @@ public String jsonKey() { } @Override - public void trace(final MessageFrame frame) { + public void enterTransaction() { + this.operations.enter(); + } + + @Override + public void popTransaction() { + this.operations.pop(); + } + + @Override + public void tracePreOpcode(final MessageFrame frame) { final OpCodeData opCode = OpCodes.of(frame.getCurrentOperation().getOpcode()); final Bytes32 arg1 = Bytes32.leftPad(frame.getStackItem(0)); final Bytes32 arg2 = diff --git a/src/test/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RandomTxrcptTests.java b/src/test/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RandomTxrcptTests.java index 8dba731f41..dd30306284 100644 --- a/src/test/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RandomTxrcptTests.java +++ b/src/test/java/net/consensys/linea/zktracer/module/rlp_txrcpt/RandomTxrcptTests.java @@ -68,6 +68,7 @@ public void testRandomTxrcpt() { final long gasUsed = rnd.nextLong(21000, 0xfffffffffffffffL); // Call the module + rlpTxrcpt.enterTransaction(); rlpTxrcpt.traceEndTx(null, tx, status, output, logs, gasUsed); }