diff --git a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracer.java b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracer.java index eba0f4ee71..82d64e8d27 100644 --- a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracer.java +++ b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracer.java @@ -15,12 +15,14 @@ package net.consensys.linea.continoustracing; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import lombok.extern.slf4j.Slf4j; import net.consensys.linea.continoustracing.exception.InvalidBlockTraceException; +import net.consensys.linea.continoustracing.exception.TraceOutputException; import net.consensys.linea.continoustracing.exception.TraceVerificationException; import net.consensys.linea.corset.CorsetValidator; import net.consensys.linea.zktracer.ZkTracer; @@ -32,18 +34,22 @@ @Slf4j public class ContinuousTracer { - private static final Optional TRACES_PATH = - Optional.ofNullable(System.getenv("TRACES_DIR")).map(Paths::get); private final TraceService traceService; private final CorsetValidator corsetValidator; + private final ContinuousTracingConfiguration continuousTracingConfiguration; + private final Optional tracesOutputPath; - public ContinuousTracer(final TraceService traceService, final CorsetValidator corsetValidator) { + public ContinuousTracer( + TraceService traceService, + CorsetValidator corsetValidator, + ContinuousTracingConfiguration continuousTracingConfiguration) { this.traceService = traceService; this.corsetValidator = corsetValidator; + this.continuousTracingConfiguration = continuousTracingConfiguration; + this.tracesOutputPath = initTracesOutputPath(); } - public CorsetValidator.Result verifyTraceOfBlock( - final Hash blockHash, final String zkEvmBin, final ZkTracer zkTracer) + public CorsetValidator.Result verifyTraceOfBlock(final Hash blockHash, final ZkTracer zkTracer) throws TraceVerificationException, InvalidBlockTraceException { zkTracer.traceStartConflation(1); @@ -53,9 +59,6 @@ public CorsetValidator.Result verifyTraceOfBlock( } catch (final Exception e) { throw new TraceVerificationException(blockHash, e.getMessage()); } finally { - // TODO: After consulting with the Arithmetization team, it is ok to pass the world state as - // null for now, but it - // should be fixed at some point. zkTracer.traceEndConflation(null); } @@ -72,8 +75,9 @@ public CorsetValidator.Result verifyTraceOfBlock( try { result = corsetValidator.validate( - TRACES_PATH.map(zkTracer::writeToTmpFile).orElseGet(zkTracer::writeToTmpFile), - zkEvmBin); + tracesOutputPath.map(zkTracer::writeToTmpFile).orElseGet(zkTracer::writeToTmpFile), + continuousTracingConfiguration.zkEvmBin()); + if (!result.isValid()) { log.error("Trace of block {} is not valid", blockHash.toHexString()); return result; @@ -93,4 +97,17 @@ public CorsetValidator.Result verifyTraceOfBlock( log.info("Trace of block {} is valid", blockHash.toHexString()); return result; } + + private Optional initTracesOutputPath() { + final Optional tracesOutputPath = + Optional.of(Paths.get(continuousTracingConfiguration.tracesDir())); + + try { + Files.createDirectories(tracesOutputPath.get()); + } catch (IOException e) { + throw new TraceOutputException(e.getMessage()); + } + + return tracesOutputPath; + } } diff --git a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingBlockAddedListener.java b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingBlockAddedListener.java index f34c255fc6..970cdef96e 100644 --- a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingBlockAddedListener.java +++ b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingBlockAddedListener.java @@ -20,6 +20,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.consensys.linea.continoustracing.exception.InvalidBlockTraceException; import net.consensys.linea.continoustracing.exception.InvalidTraceHandlerException; @@ -32,10 +33,10 @@ import org.hyperledger.besu.plugin.services.BesuEvents; @Slf4j +@RequiredArgsConstructor public class ContinuousTracingBlockAddedListener implements BesuEvents.BlockAddedListener { private final ContinuousTracer continuousTracer; private final TraceFailureHandler traceFailureHandler; - private final String zkEvmBin; static final int BLOCK_PARALLELISM = 5; final ThreadPoolExecutor pool = @@ -47,15 +48,6 @@ public class ContinuousTracingBlockAddedListener implements BesuEvents.BlockAdde new ArrayBlockingQueue<>(BLOCK_PARALLELISM), new ThreadPoolExecutor.CallerRunsPolicy()); - public ContinuousTracingBlockAddedListener( - final ContinuousTracer continuousTracer, - final TraceFailureHandler traceFailureHandler, - final String zkEvmBin) { - this.continuousTracer = continuousTracer; - this.traceFailureHandler = traceFailureHandler; - this.zkEvmBin = zkEvmBin; - } - @Override public void onBlockAdded(final AddedBlockContext addedBlockContext) { pool.submit( @@ -66,7 +58,7 @@ public void onBlockAdded(final AddedBlockContext addedBlockContext) { try { final CorsetValidator.Result traceResult = - continuousTracer.verifyTraceOfBlock(blockHash, zkEvmBin, new ZkTracer()); + continuousTracer.verifyTraceOfBlock(blockHash, new ZkTracer()); Files.delete(traceResult.traceFile().toPath()); if (!traceResult.isValid()) { diff --git a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingCliOptions.java b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingCliOptions.java index 4cc72a2ad6..c0cd403d7d 100644 --- a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingCliOptions.java +++ b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingCliOptions.java @@ -23,6 +23,9 @@ public class ContinuousTracingCliOptions { public static final String CONTINUOUS_TRACING_ZK_EVM_BIN = "--plugin-linea-continuous-tracing-zk-evm-bin"; + public static final String CONTINUOUS_TRACING_TRACES_DIR = + "--plugin-linea-continuous-tracing-traces-dir"; + @CommandLine.Option( names = {CONTINUOUS_TRACING_ENABLED}, hidden = true, @@ -37,6 +40,13 @@ public class ContinuousTracingCliOptions { description = "Path to the ZkEvm binary") private String zkEvmBin = null; + @CommandLine.Option( + names = {CONTINUOUS_TRACING_TRACES_DIR}, + hidden = true, + paramLabel = "", + description = "Path to where traces will be written") + private String tracesDir = null; + private ContinuousTracingCliOptions() {} public static ContinuousTracingCliOptions create() { @@ -44,7 +54,7 @@ public static ContinuousTracingCliOptions create() { } public ContinuousTracingConfiguration toDomainObject() { - return new ContinuousTracingConfiguration(continuousTracingEnabled, zkEvmBin); + return new ContinuousTracingConfiguration(continuousTracingEnabled, zkEvmBin, tracesDir); } @Override @@ -52,6 +62,7 @@ public String toString() { return MoreObjects.toStringHelper(this) .add(CONTINUOUS_TRACING_ENABLED, continuousTracingEnabled) .add(CONTINUOUS_TRACING_ZK_EVM_BIN, zkEvmBin) + .add(CONTINUOUS_TRACING_TRACES_DIR, tracesDir) .toString(); } } diff --git a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingConfiguration.java b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingConfiguration.java index c213b9d5b7..b803ae997d 100644 --- a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingConfiguration.java +++ b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingConfiguration.java @@ -14,4 +14,5 @@ */ package net.consensys.linea.continoustracing; -public record ContinuousTracingConfiguration(boolean continuousTracing, String zkEvmBin) {} +public record ContinuousTracingConfiguration( + boolean continuousTracing, String zkEvmBin, String tracesDir) {} diff --git a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingPlugin.java b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingPlugin.java index 8a76acf84c..7972732a58 100644 --- a/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingPlugin.java +++ b/arithmetization/src/main/java/net/consensys/linea/continoustracing/ContinuousTracingPlugin.java @@ -98,9 +98,8 @@ public void start() { besuEvents.addBlockAddedListener( new ContinuousTracingBlockAddedListener( - new ContinuousTracer(traceService, new CorsetValidator()), - new TraceFailureHandler(SlackNotificationService.create(webHookUrl)), - tracingConfiguration.zkEvmBin())); + new ContinuousTracer(traceService, new CorsetValidator(), tracingConfiguration), + new TraceFailureHandler(SlackNotificationService.create(webHookUrl)))); } @Override diff --git a/arithmetization/src/main/java/net/consensys/linea/continoustracing/exception/TraceOutputException.java b/arithmetization/src/main/java/net/consensys/linea/continoustracing/exception/TraceOutputException.java new file mode 100644 index 0000000000..c99c494c4a --- /dev/null +++ b/arithmetization/src/main/java/net/consensys/linea/continoustracing/exception/TraceOutputException.java @@ -0,0 +1,22 @@ +/* + * 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.continoustracing.exception; + +public class TraceOutputException extends RuntimeException { + public TraceOutputException(final String message) { + super( + "Trace output directory does not exist and cannot be created.\nError message: " + message); + } +} diff --git a/arithmetization/src/test/java/net/consensys/linea/continoustracing/ContinuousTracerTest.java b/arithmetization/src/test/java/net/consensys/linea/continoustracing/ContinuousTracerTest.java index 88d09aa525..60834aa23b 100644 --- a/arithmetization/src/test/java/net/consensys/linea/continoustracing/ContinuousTracerTest.java +++ b/arithmetization/src/test/java/net/consensys/linea/continoustracing/ContinuousTracerTest.java @@ -33,6 +33,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.io.TempDir; import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -43,14 +44,20 @@ public class ContinuousTracerTest { Hash.fromHexString("0x0000000000000000000000000000000000000000000000000000000000000042"); private ContinuousTracer continuousTracer; + private ContinuousTracingConfiguration continuousTracingConfiguration; @Mock TraceService traceServiceMock; @Mock CorsetValidator corsetValidatorMock; @Mock ZkTracer zkTracerMock; + @TempDir Path tracesOutputPath; + @BeforeEach void setUp() { - continuousTracer = new ContinuousTracer(traceServiceMock, corsetValidatorMock); + continuousTracingConfiguration = + new ContinuousTracingConfiguration(true, "testZkEvmBin", tracesOutputPath.toString()); + continuousTracer = + new ContinuousTracer(traceServiceMock, corsetValidatorMock, continuousTracingConfiguration); } @Test @@ -67,10 +74,8 @@ void shouldReturnSuccessIfVerificationIsSuccessful() new CorsetValidator.Result( true, Path.of("testTraceFile").toFile(), "testCorsetOutput")); - when(zkTracerMock.writeToTmpFile()).thenReturn(Path.of("")); - final CorsetValidator.Result validationResult = - continuousTracer.verifyTraceOfBlock(BLOCK_HASH, "testZkEvmBin", zkTracerMock); + continuousTracer.verifyTraceOfBlock(BLOCK_HASH, zkTracerMock); assertThat(validationResult.isValid()).isTrue(); } @@ -83,15 +88,13 @@ void shouldReturnFailureIfVerificationIsNotSuccessful() when(traceServiceMock.traceBlock(ArgumentMatchers.any(), ArgumentMatchers.any())) .thenReturn(blockTraceResult); - when(zkTracerMock.writeToTmpFile()).thenReturn(Path.of("")); - when(corsetValidatorMock.validate(ArgumentMatchers.any(), matches("testZkEvmBin"))) .thenReturn( new CorsetValidator.Result( false, Path.of("testTraceFile").toFile(), "testCorsetOutput")); final CorsetValidator.Result validationResult = - continuousTracer.verifyTraceOfBlock(BLOCK_HASH, "testZkEvmBin", zkTracerMock); + continuousTracer.verifyTraceOfBlock(BLOCK_HASH, zkTracerMock); assertThat(validationResult.isValid()).isFalse(); } @@ -105,6 +108,6 @@ void shouldThrowInvalidBlockTraceExceptionIfTracingHasInternalError() { assertThrows( InvalidBlockTraceException.class, - () -> continuousTracer.verifyTraceOfBlock(BLOCK_HASH, "testZkEvmBin", new ZkTracer())); + () -> continuousTracer.verifyTraceOfBlock(BLOCK_HASH, new ZkTracer())); } }