diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGenerator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGenerator.java index 3b955fb4cae..f24c3e07b64 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGenerator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGenerator.java @@ -13,11 +13,12 @@ package tech.pegasys.teku.statetransition.executionproofs; +import java.time.Duration; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockContainer; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; public interface ExecutionProofGenerator { SafeFuture generateExecutionProof( - SignedBlockContainer blockContainer, int subnetId); + SignedBlockContainer blockContainer, int subnetId, Duration proofGenerationDelay); } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImpl.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImpl.java index 57ac168c2ac..5f4b233f7d6 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImpl.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImpl.java @@ -14,6 +14,7 @@ package tech.pegasys.teku.statetransition.executionproofs; import java.nio.charset.Charset; +import java.time.Duration; import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -39,14 +40,17 @@ public ExecutionProofGeneratorImpl(final SchemaDefinitionsElectra schemaDefiniti @Override public SafeFuture generateExecutionProof( - final SignedBlockContainer blockContainer, final int subnetId) { + final SignedBlockContainer blockContainer, + final int subnetId, + final Duration proofGenerationDelay) { - LOG.info("Current thread {}: ", Thread.currentThread().getName()); + // delay to simulate proof generation time try { - Thread.sleep(2000); + Thread.sleep(proofGenerationDelay); } catch (InterruptedException e) { throw new RuntimeException(e); } + final ExecutionPayload executionPayload = getExecutionPayload(blockContainer); final Bytes32 blockRoot = blockContainer.getSignedBlock().getRoot(); final Bytes32 blockHash = executionPayload.getBlockHash(); diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManagerImpl.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManagerImpl.java index ba2443760ef..56bd5b6f405 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManagerImpl.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManagerImpl.java @@ -15,6 +15,7 @@ import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; +import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Optional; @@ -53,6 +54,7 @@ public class ExecutionProofManagerImpl implements ExecutionProofManager { private static final Logger LOG = LogManager.getLogger(); private final int attemptsToGetProof = 3; private final ExecutionProofGenerator executionProofGenerator; + private final Duration proofGenerationDelay; private final AsyncRunner asyncRunner; private final boolean isProofGenerationEnabled; private final int minProofsRequired; @@ -63,12 +65,14 @@ public ExecutionProofManagerImpl( final Consumer onCreatedProof, final boolean isProofGenerationEnabled, final int minProofsRequired, + final Duration proofGenerationDelay, final AsyncRunner asyncRunner) { this.executionProofGossipValidator = executionProofGossipValidator; this.onCreatedProof = onCreatedProof; this.isProofGenerationEnabled = isProofGenerationEnabled; this.minProofsRequired = minProofsRequired; this.executionProofGenerator = executionProofGenerator; + this.proofGenerationDelay = proofGenerationDelay; this.asyncRunner = asyncRunner; } @@ -128,12 +132,6 @@ public SafeFuture> validateBlockWithExec if (result.isValid()) { return SafeFuture.completedFuture(result); } - try { - Thread.sleep(100L); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return SafeFuture.completedFuture(DataAndValidationResult.notAvailable()); - } } LOG.debug("Checking proofs for block {}", block.getRoot()); @@ -173,7 +171,8 @@ public SafeFuture generateProofs(final SignedBlockContainer blockContainer .forEach( subnetIndex -> { executionProofGenerator - .generateExecutionProof(blockContainer, subnetIndex) + .generateExecutionProof( + blockContainer, subnetIndex, proofGenerationDelay) .finish( proof -> { LOG.trace("Generated proof for subnet {}", proof.getSubnetId()); diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImplTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImplTest.java index 5752b7f5628..2cc9329a831 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImplTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofGeneratorImplTest.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.time.Duration; import java.util.concurrent.ExecutionException; import org.junit.jupiter.api.Test; import tech.pegasys.teku.spec.Spec; @@ -40,8 +41,10 @@ void shouldGenerateDifferentProofsForDifferentSubnets() int subnetA = 1; int subnetB = 2; - ExecutionProof proofA = generator.generateExecutionProof(block, subnetA).get(); - ExecutionProof proofB = generator.generateExecutionProof(block, subnetB).get(); + ExecutionProof proofA = + generator.generateExecutionProof(block, subnetA, Duration.ofMillis(0)).get(); + ExecutionProof proofB = + generator.generateExecutionProof(block, subnetB, Duration.ofMillis(0)).get(); assertNotNull(proofA); assertNotNull(proofB); diff --git a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java index e66831bdf6a..755665c6aee 100644 --- a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java +++ b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainController.java @@ -719,6 +719,7 @@ protected void initZkChain() { executionProofGossipChannel::publishExecutionProof, zkConfig.generateExecutionProofsEnabled(), zkConfig.statelessMinProofsRequired(), + zkConfig.proofDelayDurationInMs(), executionProofAsyncRunner.get()); } else { diff --git a/services/zkchain/src/main/java/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java b/services/zkchain/src/main/java/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java index 35fad3a1514..5e082857ce1 100644 --- a/services/zkchain/src/main/java/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java +++ b/services/zkchain/src/main/java/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java @@ -13,14 +13,18 @@ package tech.pegasys.teku.services.zkchain; +import java.time.Duration; + public record ZkChainConfiguration( boolean statelessValidationEnabled, boolean generateExecutionProofsEnabled, - int statelessMinProofsRequired) { + int statelessMinProofsRequired, + Duration proofDelayDurationInMs) { public static final boolean DEFAULT_STATELESS_VALIDATION_ENABLED = false; public static final boolean DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED = false; public static final int DEFAULT_STATELESS_MIN_PROOFS_REQUIRED = 1; + public static final Duration DEFAULT_PROOF_GENERATION_DELAY = Duration.ofSeconds(2); public static Builder builder() { return new Builder(); @@ -31,6 +35,7 @@ public static class Builder { private boolean statelessValidationEnabled = DEFAULT_STATELESS_VALIDATION_ENABLED; private boolean generateExecutionProofsEnabled = DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED; private int statelessMinProofsRequired = DEFAULT_STATELESS_MIN_PROOFS_REQUIRED; + private Duration proofDelayDurationInMs = DEFAULT_PROOF_GENERATION_DELAY; public Builder() {} @@ -52,13 +57,21 @@ public Builder statelessMinProofsRequired(final int statelessMinProofsRequired) return this; } + public Builder proofDelayDurationInMs(final Duration proofDelayDurationInMs) { + this.proofDelayDurationInMs = proofDelayDurationInMs; + return this; + } + public ZkChainConfiguration build() { if (generateExecutionProofsEnabled && !statelessValidationEnabled) { throw new IllegalStateException( "Can't generate execution proofs when stateless validation isn't enabled"); } return new ZkChainConfiguration( - statelessValidationEnabled, generateExecutionProofsEnabled, statelessMinProofsRequired); + statelessValidationEnabled, + generateExecutionProofsEnabled, + statelessMinProofsRequired, + proofDelayDurationInMs); } } } diff --git a/teku/src/main/java/tech/pegasys/teku/cli/options/ZkChainOptions.java b/teku/src/main/java/tech/pegasys/teku/cli/options/ZkChainOptions.java index e24ea4d176c..35c727e9c9b 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/options/ZkChainOptions.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/options/ZkChainOptions.java @@ -13,6 +13,7 @@ package tech.pegasys.teku.cli.options; +import java.time.Duration; import picocli.CommandLine; import tech.pegasys.teku.config.TekuConfiguration; import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; @@ -48,12 +49,22 @@ public class ZkChainOptions { private int statelessMinProofsRequired = ZkChainConfiguration.DEFAULT_STATELESS_MIN_PROOFS_REQUIRED; + @CommandLine.Option( + hidden = true, + names = {"--Xstateless-proofs-generation-delay"}, + paramLabel = "", + description = "Proof generation artificial delay in milliseconds.", + arity = "1") + private long statelessProofGenerationDelay = + ZkChainConfiguration.DEFAULT_PROOF_GENERATION_DELAY.toMillis(); + public void configure(final TekuConfiguration.Builder builder) { builder.zkchain( zkChainConfiguration -> zkChainConfiguration .statelessValidationEnabled(statelessValidationEnabled) .generateExecutionProofsEnabled(generateExecutionProofsEnabled) - .statelessMinProofsRequired(statelessMinProofsRequired)); + .statelessMinProofsRequired(statelessMinProofsRequired) + .proofDelayDurationInMs(Duration.ofMillis(statelessProofGenerationDelay))); } } diff --git a/teku/src/test/java/tech/pegasys/teku/cli/options/ZkChainOptionsTest.java b/teku/src/test/java/tech/pegasys/teku/cli/options/ZkChainOptionsTest.java index e289eff6e8e..45dfbee6bbc 100644 --- a/teku/src/test/java/tech/pegasys/teku/cli/options/ZkChainOptionsTest.java +++ b/teku/src/test/java/tech/pegasys/teku/cli/options/ZkChainOptionsTest.java @@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.time.Duration; import org.junit.jupiter.api.Test; import tech.pegasys.teku.cli.AbstractBeaconNodeCommandTest; import tech.pegasys.teku.config.TekuConfiguration; @@ -60,4 +61,19 @@ public void generateExecutionProofsEnabled_isDisabledByDefault() { final TekuConfiguration config = getTekuConfigurationFromArguments(); assertThat(config.zkChainConfiguration().generateExecutionProofsEnabled()).isFalse(); } + + @Test + public void statelessProofGenerationDelay_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().proofDelayDurationInMs()) + .isEqualTo(Duration.ofSeconds(2)); + } + + @Test + public void statelessProofGenerationDelay_receivesCorrectValue() { + final TekuConfiguration config = + getTekuConfigurationFromArguments("--Xstateless-proofs-generation-delay=3000"); + assertThat(config.zkChainConfiguration().proofDelayDurationInMs()) + .isEqualTo(Duration.ofSeconds(3)); + } }