From 022d9fbe7ead0e3e6e26e4db381d48d71f15d122 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 1 Sep 2025 14:37:41 +1000 Subject: [PATCH 01/98] ExecutionProof container for ZkEVM L2 Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java new file mode 100644 index 00000000000..8308518f2c2 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -0,0 +1,62 @@ +package tech.pegasys.teku.spec.datastructures.execution; + +import tech.pegasys.teku.infrastructure.ssz.SszVector; +import tech.pegasys.teku.infrastructure.ssz.containers.Container4; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; +import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; +import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; + +public class ExecutionProof extends Container4> { + + public static class ExecutionProofSchema extends ContainerSchema4> { + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("proof_data", SszVectorSchema.create(SszPrimitiveSchemas.BYTE_SCHEMA, 65536)) // Assuming max size of proof_data is 65536 bytes + ); + } + + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); + } + + } + + public static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); + + private ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { + super(type, node); + } + + public ExecutionProof( + final SszBytes32 blockHash, + final SszUInt64 subnetId, + final SszUInt64 version, + final SszVector proofData) { + super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); + } + + + public SszBytes32 getBlockHash() { + return getField0(); + } + public SszUInt64 getSubnetId() { + return getField1(); + } + + public SszUInt64 getVersion() { + return getField2(); + } + + public SszVector getProofData() { + return getField3(); + } +} From 580af8af17dbb1dd1355028077f612f620ebe694 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 1 Sep 2025 14:40:09 +1000 Subject: [PATCH 02/98] spotless Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 97 +++++++++++-------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 8308518f2c2..879b81a56a9 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.SszVector; @@ -10,53 +23,59 @@ import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; -public class ExecutionProof extends Container4> { - - public static class ExecutionProofSchema extends ContainerSchema4> { - public ExecutionProofSchema() { - super( - "ExecutionProof", - namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), - namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("proof_data", SszVectorSchema.create(SszPrimitiveSchemas.BYTE_SCHEMA, 65536)) // Assuming max size of proof_data is 65536 bytes - ); - } +public class ExecutionProof + extends Container4> { - @Override - public ExecutionProof createFromBackingNode(final TreeNode node) { - return new ExecutionProof(this, node); - } + public static class ExecutionProofSchema + extends ContainerSchema4< + ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema( + "proof_data", + SszVectorSchema.create( + SszPrimitiveSchemas.BYTE_SCHEMA, + 65536)) // Assuming max size of proof_data is 65536 bytes + ); + } + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); } + } - public static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); + public static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); - private ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { - super(type, node); - } + private ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { + super(type, node); + } - public ExecutionProof( - final SszBytes32 blockHash, - final SszUInt64 subnetId, - final SszUInt64 version, - final SszVector proofData) { - super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); - } + public ExecutionProof( + final SszBytes32 blockHash, + final SszUInt64 subnetId, + final SszUInt64 version, + final SszVector proofData) { + super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); + } + public SszBytes32 getBlockHash() { + return getField0(); + } - public SszBytes32 getBlockHash() { - return getField0(); - } - public SszUInt64 getSubnetId() { - return getField1(); - } + public SszUInt64 getSubnetId() { + return getField1(); + } - public SszUInt64 getVersion() { - return getField2(); - } + public SszUInt64 getVersion() { + return getField2(); + } - public SszVector getProofData() { - return getField3(); - } + public SszVector getProofData() { + return getField3(); + } } From b6230a8dcfbee1dd333789f97bb31f0dc01a0583 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 1 Sep 2025 20:10:49 +1000 Subject: [PATCH 03/98] config and cli options Signed-off-by: Gabriel Fukushima --- .../zkchain/ZkChainConfiguration.java | 69 +++++++++++++++++++ .../pegasys/teku/cli/BeaconNodeCommand.java | 5 ++ .../teku/cli/options/ZkChainOptions.java | 30 ++++++++ .../teku/config/TekuConfiguration.java | 20 +++++- 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java create mode 100644 teku/src/main/java/tech/pegasys/teku/cli/options/ZkChainOptions.java diff --git a/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java b/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java new file mode 100644 index 00000000000..a75b2f1444c --- /dev/null +++ b/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java @@ -0,0 +1,69 @@ +package tech.pegasys.teku.services.zkchain; + +public class ZkChainConfiguration { + + 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; + + + private final boolean statelessValidationEnabled; + private final boolean generateExecutionProofsEnabled; + private final int statelessMinProofsRequired; + + public ZkChainConfiguration(final boolean statelessValidationEnabled, final boolean generateExecutionProofsEnabled, final int statelessMinProofsRequired) { + this.statelessValidationEnabled = statelessValidationEnabled; + this.generateExecutionProofsEnabled = generateExecutionProofsEnabled; + this.statelessMinProofsRequired = statelessMinProofsRequired; + } + + public boolean isStatelessValidationEnabled() { + return statelessValidationEnabled; + } + + public boolean isGenerateExecutionProofsEnabled() { + return generateExecutionProofsEnabled; + } + + public int getStatelessMinProofsRequired() { + return statelessMinProofsRequired; + } + + public static Builder builder() { + return new Builder(); + } + + 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; + + public Builder() {} + + public Builder statelessValidationEnabled(final boolean statelessValidationEnabled) { + this.statelessValidationEnabled = statelessValidationEnabled; + return this; + } + + public Builder generateExecutionProofsEnabled(final boolean generateExecutionProofsEnabled) { + this.generateExecutionProofsEnabled = generateExecutionProofsEnabled; + return this; + } + + public Builder statelessMinProofsRequired(final int statelessMinProofsRequired) { + if (statelessMinProofsRequired < 1) { + throw new IllegalArgumentException("statelessMinProofsRequired must be at least 1"); + } + this.statelessMinProofsRequired = statelessMinProofsRequired; + return this; + } + + public ZkChainConfiguration build() { + return new ZkChainConfiguration(statelessValidationEnabled, + generateExecutionProofsEnabled, + statelessMinProofsRequired); + } + } + +} diff --git a/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java b/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java index bda3b7630fe..fb6d3c6b498 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java @@ -49,6 +49,7 @@ import tech.pegasys.teku.cli.options.ValidatorOptions; import tech.pegasys.teku.cli.options.ValidatorRestApiOptions; import tech.pegasys.teku.cli.options.WeakSubjectivityOptions; +import tech.pegasys.teku.cli.options.ZkChainOptions; import tech.pegasys.teku.cli.subcommand.GenesisCommand; import tech.pegasys.teku.cli.subcommand.MigrateDatabaseCommand; import tech.pegasys.teku.cli.subcommand.PeerCommand; @@ -173,6 +174,9 @@ private static class ConfigFileCommand { @Mixin(name = "Metrics") private final MetricsOptions metricsOptions = new MetricsOptions(); + @Mixin(name = "ZK-Chain") + private final ZkChainOptions zkChainOptions = new ZkChainOptions(); + @CommandLine.Spec private CommandLine.Model.CommandSpec spec; private final ValidatorClientCommand validatorClientSubcommand; @@ -419,6 +423,7 @@ protected TekuConfiguration tekuConfiguration() { beaconNodeDataOptions.configure(builder); metricsOptions.configure(builder); storeOptions.configure(builder); + zkChainOptions.configure(builder); return builder.build(); } catch (IllegalArgumentException | NullPointerException e) { 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 new file mode 100644 index 00000000000..b7365d5562e --- /dev/null +++ b/teku/src/main/java/tech/pegasys/teku/cli/options/ZkChainOptions.java @@ -0,0 +1,30 @@ +package tech.pegasys.teku.cli.options; + +import picocli.CommandLine; +import tech.pegasys.teku.config.TekuConfiguration; +import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; + +public class ZkChainOptions { + @CommandLine.Option( + names = {"--Xstateless-validation-enabled"}, + description = "Enable stateless validation of blocks and states.") + private boolean statelessValidationEnabled = ZkChainConfiguration.DEFAULT_STATELESS_VALIDATION_ENABLED; + + @CommandLine.Option( + names = {"--Xgenerate-execution-proofs-enabled"}, + description = "Enable generation of execution proofs for blocks.") + private boolean generateExecutionProofsEnabled = ZkChainConfiguration.DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED; + + @CommandLine.Option( + names = {"--Xstateless-min-proofs-required"}, + description = "Minimum number of execution proofs required for stateless validation. Must be at least 1.") + private int statelessMinProofsRequired = ZkChainConfiguration.DEFAULT_STATELESS_MIN_PROOFS_REQUIRED; + + public void configure(final TekuConfiguration.Builder builder) { + builder.zkchain(zkChainConfiguration -> + zkChainConfiguration + .statelessValidationEnabled(statelessValidationEnabled) + .generateExecutionProofsEnabled(generateExecutionProofsEnabled) + .statelessMinProofsRequired(statelessMinProofsRequired)); + } +} diff --git a/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java b/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java index df901bdcfbb..fb904d4da81 100644 --- a/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java +++ b/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java @@ -33,6 +33,7 @@ import tech.pegasys.teku.services.beaconchain.BeaconChainControllerFactory; import tech.pegasys.teku.services.executionlayer.ExecutionLayerConfiguration; import tech.pegasys.teku.services.powchain.PowchainConfiguration; +import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.config.NetworkingSpecConfigDeneb; import tech.pegasys.teku.storage.server.StorageConfiguration; @@ -56,6 +57,7 @@ public class TekuConfiguration { private final ExecutionLayerConfiguration executionLayerConfiguration; private final NatConfiguration natConfiguration; private final ValidatorRestApiConfig validatorRestApiConfig; + private final ZkChainConfiguration zkChainConfiguration; private TekuConfiguration( final Eth2NetworkConfiguration eth2NetworkConfiguration, @@ -74,7 +76,8 @@ private TekuConfiguration( final StoreConfig storeConfig, final NatConfiguration natConfiguration, final ValidatorRestApiConfig validatorRestApiConfig, - final BeaconChainControllerFactory beaconChainControllerFactory) { + final BeaconChainControllerFactory beaconChainControllerFactory, + final ZkChainConfiguration zkChainConfiguration) { this.eth2NetworkConfiguration = eth2NetworkConfiguration; this.storageConfiguration = storageConfiguration; this.weakSubjectivityConfig = weakSubjectivityConfig; @@ -101,6 +104,7 @@ private TekuConfiguration( validatorConfig, interopConfig, validatorRestApiConfig, spec); this.natConfiguration = natConfiguration; this.validatorRestApiConfig = validatorRestApiConfig; + this.zkChainConfiguration = zkChainConfiguration; } public static Builder builder() { @@ -167,6 +171,8 @@ public ValidatorRestApiConfig validatorRestApiConfig() { return validatorRestApiConfig; } + public ZkChainConfiguration zkChainConfiguration() { return zkChainConfiguration; } + public static class Builder { private final Eth2NetworkConfiguration.Builder eth2NetworkConfigurationBuilder = Eth2NetworkConfiguration.builder().applyMainnetNetworkDefaults(); @@ -177,6 +183,8 @@ public static class Builder { private final ValidatorConfig.Builder validatorConfigBuilder = ValidatorConfig.builder(); private final PowchainConfiguration.Builder powchainConfigBuilder = PowchainConfiguration.builder(); + private final ZkChainConfiguration.Builder zkChainConfigBuilder = + ZkChainConfiguration.builder(); private final ExecutionLayerConfiguration.Builder executionLayerConfigBuilder = ExecutionLayerConfiguration.builder(); private final InteropConfig.InteropConfigBuilder interopConfigBuilder = InteropConfig.builder(); @@ -241,6 +249,8 @@ public TekuConfiguration build() { final SyncConfig syncConfig = syncConfigBuilder.build(); + final ZkChainConfiguration zkChainConfiguration = zkChainConfigBuilder.build(); + final long maxAllowedBatchSize = spec.getNetworkingConfigDeneb() .map(NetworkingSpecConfigDeneb::getMaxRequestBlocksDeneb) @@ -316,7 +326,8 @@ public TekuConfiguration build() { storeConfigBuilder.build(), natConfigBuilder.build(), validatorRestApiConfigBuilder.build(), - beaconChainControllerFactory); + beaconChainControllerFactory, + zkChainConfiguration); } public Builder eth2NetworkConfig(final Consumer consumer) { @@ -350,6 +361,11 @@ public Builder powchain(final Consumer consumer) return this; } + public Builder zkchain(final Consumer consumer) { + consumer.accept(zkChainConfigBuilder); + return this; + } + public Builder executionLayer(final Consumer consumer) { consumer.accept(executionLayerConfigBuilder); return this; From a0f6f62498f99f81e0480ca2c4ae934e6a727a90 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 1 Sep 2025 20:11:06 +1000 Subject: [PATCH 04/98] spotless Signed-off-by: Gabriel Fukushima --- .../zkchain/ZkChainConfiguration.java | 117 ++++++++++-------- .../pegasys/teku/cli/BeaconNodeCommand.java | 2 +- .../teku/cli/options/ZkChainOptions.java | 56 ++++++--- .../teku/config/TekuConfiguration.java | 4 +- 4 files changed, 106 insertions(+), 73 deletions(-) diff --git a/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java b/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java index a75b2f1444c..c7f4eed7c12 100644 --- a/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java +++ b/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java @@ -1,69 +1,82 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.services.zkchain; public class ZkChainConfiguration { - 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 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; + private final boolean statelessValidationEnabled; + private final boolean generateExecutionProofsEnabled; + private final int statelessMinProofsRequired; - private final boolean statelessValidationEnabled; - private final boolean generateExecutionProofsEnabled; - private final int statelessMinProofsRequired; + public ZkChainConfiguration( + final boolean statelessValidationEnabled, + final boolean generateExecutionProofsEnabled, + final int statelessMinProofsRequired) { + this.statelessValidationEnabled = statelessValidationEnabled; + this.generateExecutionProofsEnabled = generateExecutionProofsEnabled; + this.statelessMinProofsRequired = statelessMinProofsRequired; + } - public ZkChainConfiguration(final boolean statelessValidationEnabled, final boolean generateExecutionProofsEnabled, final int statelessMinProofsRequired) { - this.statelessValidationEnabled = statelessValidationEnabled; - this.generateExecutionProofsEnabled = generateExecutionProofsEnabled; - this.statelessMinProofsRequired = statelessMinProofsRequired; - } + public boolean isStatelessValidationEnabled() { + return statelessValidationEnabled; + } - public boolean isStatelessValidationEnabled() { - return statelessValidationEnabled; - } + public boolean isGenerateExecutionProofsEnabled() { + return generateExecutionProofsEnabled; + } - public boolean isGenerateExecutionProofsEnabled() { - return generateExecutionProofsEnabled; - } + public int getStatelessMinProofsRequired() { + return statelessMinProofsRequired; + } + + public static Builder builder() { + return new Builder(); + } - public int getStatelessMinProofsRequired() { - return statelessMinProofsRequired; + 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; + + public Builder() {} + + public Builder statelessValidationEnabled(final boolean statelessValidationEnabled) { + this.statelessValidationEnabled = statelessValidationEnabled; + return this; } - public static Builder builder() { - return new Builder(); + public Builder generateExecutionProofsEnabled(final boolean generateExecutionProofsEnabled) { + this.generateExecutionProofsEnabled = generateExecutionProofsEnabled; + return this; } - 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; - - public Builder() {} - - public Builder statelessValidationEnabled(final boolean statelessValidationEnabled) { - this.statelessValidationEnabled = statelessValidationEnabled; - return this; - } - - public Builder generateExecutionProofsEnabled(final boolean generateExecutionProofsEnabled) { - this.generateExecutionProofsEnabled = generateExecutionProofsEnabled; - return this; - } - - public Builder statelessMinProofsRequired(final int statelessMinProofsRequired) { - if (statelessMinProofsRequired < 1) { - throw new IllegalArgumentException("statelessMinProofsRequired must be at least 1"); - } - this.statelessMinProofsRequired = statelessMinProofsRequired; - return this; - } - - public ZkChainConfiguration build() { - return new ZkChainConfiguration(statelessValidationEnabled, - generateExecutionProofsEnabled, - statelessMinProofsRequired); - } + public Builder statelessMinProofsRequired(final int statelessMinProofsRequired) { + if (statelessMinProofsRequired < 1) { + throw new IllegalArgumentException("statelessMinProofsRequired must be at least 1"); + } + this.statelessMinProofsRequired = statelessMinProofsRequired; + return this; } + public ZkChainConfiguration build() { + return new ZkChainConfiguration( + statelessValidationEnabled, generateExecutionProofsEnabled, statelessMinProofsRequired); + } + } } diff --git a/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java b/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java index fb6d3c6b498..a268f97d510 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/BeaconNodeCommand.java @@ -175,7 +175,7 @@ private static class ConfigFileCommand { private final MetricsOptions metricsOptions = new MetricsOptions(); @Mixin(name = "ZK-Chain") - private final ZkChainOptions zkChainOptions = new ZkChainOptions(); + private final ZkChainOptions zkChainOptions = new ZkChainOptions(); @CommandLine.Spec private CommandLine.Model.CommandSpec spec; 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 b7365d5562e..6a6c5eb0a89 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 @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.cli.options; import picocli.CommandLine; @@ -5,26 +18,31 @@ import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; public class ZkChainOptions { - @CommandLine.Option( - names = {"--Xstateless-validation-enabled"}, - description = "Enable stateless validation of blocks and states.") - private boolean statelessValidationEnabled = ZkChainConfiguration.DEFAULT_STATELESS_VALIDATION_ENABLED; + @CommandLine.Option( + names = {"--Xstateless-validation-enabled"}, + description = "Enable stateless validation of blocks and states.") + private boolean statelessValidationEnabled = + ZkChainConfiguration.DEFAULT_STATELESS_VALIDATION_ENABLED; - @CommandLine.Option( - names = {"--Xgenerate-execution-proofs-enabled"}, - description = "Enable generation of execution proofs for blocks.") - private boolean generateExecutionProofsEnabled = ZkChainConfiguration.DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED; + @CommandLine.Option( + names = {"--Xgenerate-execution-proofs-enabled"}, + description = "Enable generation of execution proofs for blocks.") + private boolean generateExecutionProofsEnabled = + ZkChainConfiguration.DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED; - @CommandLine.Option( - names = {"--Xstateless-min-proofs-required"}, - description = "Minimum number of execution proofs required for stateless validation. Must be at least 1.") - private int statelessMinProofsRequired = ZkChainConfiguration.DEFAULT_STATELESS_MIN_PROOFS_REQUIRED; + @CommandLine.Option( + names = {"--Xstateless-min-proofs-required"}, + description = + "Minimum number of execution proofs required for stateless validation. Must be at least 1.") + private int statelessMinProofsRequired = + ZkChainConfiguration.DEFAULT_STATELESS_MIN_PROOFS_REQUIRED; - public void configure(final TekuConfiguration.Builder builder) { - builder.zkchain(zkChainConfiguration -> - zkChainConfiguration - .statelessValidationEnabled(statelessValidationEnabled) - .generateExecutionProofsEnabled(generateExecutionProofsEnabled) - .statelessMinProofsRequired(statelessMinProofsRequired)); - } + public void configure(final TekuConfiguration.Builder builder) { + builder.zkchain( + zkChainConfiguration -> + zkChainConfiguration + .statelessValidationEnabled(statelessValidationEnabled) + .generateExecutionProofsEnabled(generateExecutionProofsEnabled) + .statelessMinProofsRequired(statelessMinProofsRequired)); + } } diff --git a/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java b/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java index fb904d4da81..09d27c8fa8f 100644 --- a/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java +++ b/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java @@ -171,7 +171,9 @@ public ValidatorRestApiConfig validatorRestApiConfig() { return validatorRestApiConfig; } - public ZkChainConfiguration zkChainConfiguration() { return zkChainConfiguration; } + public ZkChainConfiguration zkChainConfiguration() { + return zkChainConfiguration; + } public static class Builder { private final Eth2NetworkConfiguration.Builder eth2NetworkConfigurationBuilder = From 468fa819c3552c0d9f5227178052eb0ee5a83ebc Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 09:51:49 +1000 Subject: [PATCH 05/98] add execution proof to the schema registry under phase0 so we can support any milestone Signed-off-by: Gabriel Fukushima --- .../spec/schemas/registry/SchemaRegistryBuilder.java | 11 +++++++++++ .../teku/spec/schemas/registry/SchemaTypes.java | 3 +++ 2 files changed, 14 insertions(+) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index e9754787a3d..7fb96285f1c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -54,6 +54,7 @@ import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_AND_BLOBS_CELL_BUNDLE_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_HEADER_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_SCHEMA; +import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PROOF_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_REQUESTS_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.HISTORICAL_BATCH_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.HISTORICAL_SUMMARIES_SCHEMA; @@ -123,6 +124,7 @@ import tech.pegasys.teku.spec.datastructures.builder.versions.electra.BuilderBidSchemaElectra; import tech.pegasys.teku.spec.datastructures.builder.versions.fulu.BlobsBundleSchemaFulu; import tech.pegasys.teku.spec.datastructures.builder.versions.fulu.ExecutionPayloadAndBlobsCellBundleSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.ExecutionPayloadHeaderSchemaCapella; @@ -192,6 +194,7 @@ public static SchemaRegistryBuilder create() { .addProvider(createBeaconStateSchemaProvider()) .addProvider(createMetadataMessageSchemaProvider()) .addProvider(createStatusMessageSchemaProvider()) + .addProvider(createExecutionProofSchemaProvider()) // BELLATRIX .addProvider(createExecutionPayloadSchemaProvider()) @@ -845,6 +848,14 @@ private static SchemaProvider createStatusMessageSchemaProvider() { .build(); } + private static SchemaProvider createExecutionProofSchemaProvider(){ + return providerBuilder(EXECUTION_PROOF_SCHEMA) + .withCreator( + PHASE0, + (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) + .build(); + } + private static long getMaxValidatorsPerAttestationPhase0(final SpecConfig specConfig) { return specConfig.getMaxValidatorsPerCommittee(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index e2ba0001b8f..e4e3176f3f4 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -50,6 +50,7 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.WithdrawalSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequestSchema; @@ -118,6 +119,8 @@ public class SchemaTypes { create("METADATA_MESSAGE_SCHEMA"); public static final SchemaId> STATUS_MESSAGE_SCHEMA = create("STATUS_MESSAGE_SCHEMA"); + public static final SchemaId EXECUTION_PROOF_SCHEMA = + create("EXECUTION_PROOF_SCHEMA"); // Altair From e8c52bb87173b68799a4df53bb09c68fbe213715 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 09:52:01 +1000 Subject: [PATCH 06/98] spotless Signed-off-by: Gabriel Fukushima --- .../schemas/registry/SchemaRegistryBuilder.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 7fb96285f1c..b4aa72c468c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -848,13 +848,12 @@ private static SchemaProvider createStatusMessageSchemaProvider() { .build(); } - private static SchemaProvider createExecutionProofSchemaProvider(){ - return providerBuilder(EXECUTION_PROOF_SCHEMA) - .withCreator( - PHASE0, - (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) - .build(); - } + private static SchemaProvider createExecutionProofSchemaProvider() { + return providerBuilder(EXECUTION_PROOF_SCHEMA) + .withCreator( + PHASE0, (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) + .build(); + } private static long getMaxValidatorsPerAttestationPhase0(final SpecConfig specConfig) { return specConfig.getMaxValidatorsPerCommittee(); From 30063242f65c840c81b4c2c88fccbaf67167125b Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 10:55:50 +1000 Subject: [PATCH 07/98] fix assemble Signed-off-by: Gabriel Fukushima --- services/zkchain/build.gradle | 3 +++ .../pegasys/teku/services/zkchain/ZkChainConfiguration.java | 0 settings.gradle | 4 ++-- teku/build.gradle | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 services/zkchain/build.gradle rename services/zkchain/src/{ => main/java}/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java (100%) diff --git a/services/zkchain/build.gradle b/services/zkchain/build.gradle new file mode 100644 index 00000000000..2e3ca6ab498 --- /dev/null +++ b/services/zkchain/build.gradle @@ -0,0 +1,3 @@ +dependencies { + +} diff --git a/services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java b/services/zkchain/src/main/java/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java similarity index 100% rename from services/zkchain/src/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java rename to services/zkchain/src/main/java/tech/pegasys/teku/services/zkchain/ZkChainConfiguration.java diff --git a/settings.gradle b/settings.gradle index a13660aa897..06e1fc9d521 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -rootProject.name='teku' +rootProject.name = 'teku' include 'acceptance-tests' include 'beacon:pow' include 'beacon:sync' @@ -69,4 +69,4 @@ include 'eth-reference-tests' include 'eth-benchmark-tests' include 'fork-choice-tests' include 'ethereum:performance-trackers' - +include 'services:zkchain' \ No newline at end of file diff --git a/teku/build.gradle b/teku/build.gradle index 6f74567ea18..aa583bc45b7 100644 --- a/teku/build.gradle +++ b/teku/build.gradle @@ -33,6 +33,7 @@ dependencies { implementation project(':services:chainstorage') implementation project(':services:executionlayer') implementation project(':services:powchain') + implementation project(':services:zkchain') implementation project(':infrastructure:serviceutils') implementation project(':services:timer') implementation project(':storage') From cd8f5aed3e8e150f162986fbced52fc45c7e0cc5 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 11:35:05 +1000 Subject: [PATCH 08/98] add hidden to flags and fallback values Signed-off-by: Gabriel Fukushima --- .../teku/cli/options/ZkChainOptions.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) 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 6a6c5eb0a89..0c635a8d3c5 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 @@ -19,21 +19,32 @@ public class ZkChainOptions { @CommandLine.Option( + hidden = true, names = {"--Xstateless-validation-enabled"}, - description = "Enable stateless validation of blocks and states.") + showDefaultValue = CommandLine.Help.Visibility.ALWAYS, + description = "Enable stateless validation of blocks and states.", + arity = "0..1", + fallbackValue = "false") private boolean statelessValidationEnabled = ZkChainConfiguration.DEFAULT_STATELESS_VALIDATION_ENABLED; @CommandLine.Option( + hidden = true, names = {"--Xgenerate-execution-proofs-enabled"}, - description = "Enable generation of execution proofs for blocks.") + showDefaultValue = CommandLine.Help.Visibility.ALWAYS, + description = "Enable generation of execution proofs for blocks.", + arity = "0..1", + fallbackValue = "false") private boolean generateExecutionProofsEnabled = ZkChainConfiguration.DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED; @CommandLine.Option( + hidden = true, names = {"--Xstateless-min-proofs-required"}, + paramLabel = "", description = - "Minimum number of execution proofs required for stateless validation. Must be at least 1.") + "Minimum number of execution proofs required for stateless validation. Must be at least 1.", + arity = "1") private int statelessMinProofsRequired = ZkChainConfiguration.DEFAULT_STATELESS_MIN_PROOFS_REQUIRED; From 2f42260121e69bacf745fafb785ae4452375156f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 11:37:42 +1000 Subject: [PATCH 09/98] fix fallback values Signed-off-by: Gabriel Fukushima --- .../java/tech/pegasys/teku/cli/options/ZkChainOptions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 0c635a8d3c5..e24ea4d176c 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 @@ -24,7 +24,7 @@ public class ZkChainOptions { showDefaultValue = CommandLine.Help.Visibility.ALWAYS, description = "Enable stateless validation of blocks and states.", arity = "0..1", - fallbackValue = "false") + fallbackValue = "true") private boolean statelessValidationEnabled = ZkChainConfiguration.DEFAULT_STATELESS_VALIDATION_ENABLED; @@ -34,7 +34,7 @@ public class ZkChainOptions { showDefaultValue = CommandLine.Help.Visibility.ALWAYS, description = "Enable generation of execution proofs for blocks.", arity = "0..1", - fallbackValue = "false") + fallbackValue = "true") private boolean generateExecutionProofsEnabled = ZkChainConfiguration.DEFAULT_GENERATE_EXECUTION_PROOFS_ENABLED; From 7f4e13e49839a57933d0a82e5979386e527f4546 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 12:41:00 +1000 Subject: [PATCH 10/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/spec/schemas/registry/SchemaRegistryBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 68d088f30d6..f2dc974e675 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -129,10 +129,10 @@ import tech.pegasys.teku.spec.datastructures.builder.versions.electra.BuilderBidSchemaElectra; import tech.pegasys.teku.spec.datastructures.builder.versions.fulu.BlobsBundleSchemaFulu; import tech.pegasys.teku.spec.datastructures.builder.versions.fulu.ExecutionPayloadAndBlobsCellBundleSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationDataSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadHeaderSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.ExecutionPayloadHeaderSchemaCapella; From 6011bc7abd695df2dd8e93dba56d5d02e7cb33e4 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 12:49:54 +1000 Subject: [PATCH 11/98] move the execution proof to electra Signed-off-by: Gabriel Fukushima --- .../teku/spec/schemas/registry/SchemaRegistryBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index f2dc974e675..2e9ac5bfecf 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -204,7 +204,7 @@ public static SchemaRegistryBuilder create() { .addProvider(createBeaconStateSchemaProvider()) .addProvider(createMetadataMessageSchemaProvider()) .addProvider(createStatusMessageSchemaProvider()) - .addProvider(createExecutionProofSchemaProvider()) + // BELLATRIX .addProvider(createExecutionPayloadSchemaProvider()) @@ -241,6 +241,7 @@ public static SchemaRegistryBuilder create() { .addProvider(createConsolidationRequestSchemaProvider()) .addProvider(createExecutionRequestsSchemaProvider()) .addProvider(createSingleAttestationSchemaProvider()) + .addProvider(createExecutionProofSchemaProvider()) // FULU .addProvider(createCellSchemaProvider()) @@ -881,7 +882,7 @@ private static SchemaProvider createStatusMessageSchemaProvider() { private static SchemaProvider createExecutionProofSchemaProvider() { return providerBuilder(EXECUTION_PROOF_SCHEMA) .withCreator( - PHASE0, (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) + ELECTRA, (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) .build(); } From 6d2445376337a84db7065f827f7fbad9e6bbc9a5 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 13:36:14 +1000 Subject: [PATCH 12/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/spec/schemas/registry/SchemaRegistryBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 2e9ac5bfecf..2ea676979bb 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -205,7 +205,6 @@ public static SchemaRegistryBuilder create() { .addProvider(createMetadataMessageSchemaProvider()) .addProvider(createStatusMessageSchemaProvider()) - // BELLATRIX .addProvider(createExecutionPayloadSchemaProvider()) .addProvider(createExecutionPayloadHeaderSchemaProvider()) @@ -882,7 +881,8 @@ private static SchemaProvider createStatusMessageSchemaProvider() { private static SchemaProvider createExecutionProofSchemaProvider() { return providerBuilder(EXECUTION_PROOF_SCHEMA) .withCreator( - ELECTRA, (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) + ELECTRA, + (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) .build(); } From 00f8fdf8147ae11ff0fdb17a9237b64ed98f70d1 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 14:25:48 +1000 Subject: [PATCH 13/98] initial boilerplate Signed-off-by: Gabriel Fukushima --- .../networking/eth2/ActiveEth2P2PNetwork.java | 14 ++++++++++++++ .../teku/networking/eth2/Eth2P2PNetwork.java | 4 ++++ .../eth2/gossip/forks/GossipForkManager.java | 15 +++++++++++++++ .../gossip/forks/GossipForkSubscriptions.java | 8 ++++++++ .../networking/eth2/mock/NoOpEth2P2PNetwork.java | 6 ++++++ 5 files changed, 47 insertions(+) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java index f9617f7940e..829d8db4607 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java @@ -72,6 +72,7 @@ public class ActiveEth2P2PNetwork extends DelegatingP2PNetwork impleme private final SubnetSubscriptionService attestationSubnetService; private final SubnetSubscriptionService syncCommitteeSubnetService; private final SubnetSubscriptionService dataColumnSidecarSubnetService; + private final SubnetSubscriptionService executionProofSubnetService; private final ProcessedAttestationSubscriptionProvider processedAttestationSubscriptionProvider; private final AtomicBoolean gossipStarted = new AtomicBoolean(false); private final int dasTotalCustodySubnetCount; @@ -115,6 +116,7 @@ public ActiveEth2P2PNetwork( this.attestationSubnetService = attestationSubnetService; this.syncCommitteeSubnetService = syncCommitteeSubnetService; this.dataColumnSidecarSubnetService = dataColumnSidecarSubnetService; + this.executionProofSubnetService = executionProofSubnetService; this.processedAttestationSubscriptionProvider = processedAttestationSubscriptionProvider; this.dasTotalCustodySubnetCount = dasTotalCustodySubnetCount; this.allTopicsFilterEnabled = allTopicsFilterEnabled; @@ -355,12 +357,24 @@ public void subscribeToDataColumnSidecarSubnetId(final int subnetId) { dataColumnSidecarSubnetService.addSubscription(subnetId); } + @Override + public void subscribeToExecutionProofSubnetId(final int subnetId) { + gossipForkManager.subscribeToExecutionProofSubnetId(subnetId); + executionProofSubnetService.addSubscription(subnetId); + } + @Override public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) { gossipForkManager.unsubscribeFromDataColumnSidecarSubnetId(subnetId); dataColumnSidecarSubnetService.removeSubscription(subnetId); } + @Override + public void unsubscribeFromExecutionProofSubnetId(final int subnetId) { + gossipForkManager.unsubscribeFromExecutionProofSubnetId(subnetId); + executionProofSubnetService.removeSubscription(subnetId); + } + @Override public MetadataMessage getMetadata() { return peerManager.getMetadataMessage(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java index 8d1b926bb79..59c407dbb77 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java @@ -40,10 +40,14 @@ public interface Eth2P2PNetwork extends P2PNetwork { void unsubscribeFromSyncCommitteeSubnetId(int subnetId); + void subscribeToExecutionProofSubnetId(int subnetId); + void subscribeToDataColumnSidecarSubnetId(int subnetId); void unsubscribeFromDataColumnSidecarSubnetId(int subnetId); + void unsubscribeFromExecutionProofSubnetId(int subnetId); + MetadataMessage getMetadata(); void publishSyncCommitteeMessage(ValidatableSyncCommitteeMessage message); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index b49579cf006..19738920926 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -65,6 +65,7 @@ public class GossipForkManager { private final IntSet currentAttestationSubnets = new IntOpenHashSet(); private final IntSet currentSyncCommitteeSubnets = new IntOpenHashSet(); private final IntSet currentDataColumnSidecarSubnets = new IntOpenHashSet(); + private final IntSet currentExecutionProofSubnets = new IntOpenHashSet(); private Optional currentEpoch = Optional.empty(); private boolean isHeadOptimistic; @@ -317,6 +318,20 @@ public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) { } } + public void subscribeToExecutionProofSubnetId(final int subnetId) { + if (currentExecutionProofSubnets.add(subnetId)) { + activeSubscriptions.forEach( + subscription -> subscription.subscribeToExecutionProofSubnet(subnetId)); + } + } + + public void unsubscribeFromExecutionProofSubnetId(final int subnetId) { + if (currentExecutionProofSubnets.remove(subnetId)) { + activeSubscriptions.forEach( + subscription -> subscription.unsubscribeFromExecutionProofSubnet(subnetId)); + } + } + private boolean isActive(final GossipForkSubscriptions subscriptions) { return activeSubscriptions.contains(subscriptions); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index ee30139ab71..c1643e8058b 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -84,4 +84,12 @@ default void subscribeToDataColumnSidecarSubnet(final int subnetId) { default void unsubscribeFromDataColumnSidecarSubnet(final int subnetId) { // since Fulu } + + default void subscribeToExecutionProofSubnet(final int subnetId) { + // since Electra + } + + default void unsubscribeFromExecutionProofSubnet(final int subnetId) { + // since Electra + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/mock/NoOpEth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/mock/NoOpEth2P2PNetwork.java index 15579a5a28c..7ae510a76e8 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/mock/NoOpEth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/mock/NoOpEth2P2PNetwork.java @@ -60,6 +60,12 @@ public void subscribeToDataColumnSidecarSubnetId(final int subnetId) {} @Override public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) {} + @Override + public void subscribeToExecutionProofSubnetId(final int subnetId) {} + + @Override + public void unsubscribeFromExecutionProofSubnetId(final int subnetId) {} + @Override public MetadataMessage getMetadata() { return spec.getGenesisSchemaDefinitions().getMetadataMessageSchema().createDefault(); From f37f4be52083538244a36969e227295e3b10d16b Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 16:30:12 +1000 Subject: [PATCH 14/98] separate schema from class Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 27 ++------------- .../execution/ExecutionProofSchema.java | 34 +++++++++++++++++++ .../registry/SchemaRegistryBuilder.java | 3 +- .../spec/schemas/registry/SchemaTypes.java | 3 +- 4 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 879b81a56a9..29fd84c2644 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -26,32 +26,9 @@ public class ExecutionProof extends Container4> { - public static class ExecutionProofSchema - extends ContainerSchema4< - ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { - public ExecutionProofSchema() { - super( - "ExecutionProof", - namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), - namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema( - "proof_data", - SszVectorSchema.create( - SszPrimitiveSchemas.BYTE_SCHEMA, - 65536)) // Assuming max size of proof_data is 65536 bytes - ); - } + private static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); - @Override - public ExecutionProof createFromBackingNode(final TreeNode node) { - return new ExecutionProof(this, node); - } - } - - public static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); - - private ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { + public ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { super(type, node); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java new file mode 100644 index 00000000000..075cb6ac612 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -0,0 +1,34 @@ +package tech.pegasys.teku.spec.datastructures.execution; + +import tech.pegasys.teku.infrastructure.ssz.SszVector; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; +import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; +import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; + +public class ExecutionProofSchema + extends ContainerSchema4< + ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { + + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema( + "proof_data", + SszVectorSchema.create( + SszPrimitiveSchemas.BYTE_SCHEMA, + 65536)) // Assuming max size of proof_data is 65536 bytes + ); + } + + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); + } +} \ No newline at end of file diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 2ea676979bb..9cf96c7333b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -133,6 +133,7 @@ import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.ExecutionPayloadHeaderSchemaCapella; @@ -882,7 +883,7 @@ private static SchemaProvider createExecutionProofSchemaProvider() { return providerBuilder(EXECUTION_PROOF_SCHEMA) .withCreator( ELECTRA, - (registry, specConfig, schemaName) -> new ExecutionProof.ExecutionProofSchema()) + (registry, specConfig, schemaName) -> new ExecutionProofSchema()) .build(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index 3c932b622a0..5af7989929b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -54,6 +54,7 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.WithdrawalSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequestSchema; @@ -122,7 +123,7 @@ public class SchemaTypes { create("METADATA_MESSAGE_SCHEMA"); public static final SchemaId> STATUS_MESSAGE_SCHEMA = create("STATUS_MESSAGE_SCHEMA"); - public static final SchemaId EXECUTION_PROOF_SCHEMA = + public static final SchemaId EXECUTION_PROOF_SCHEMA = create("EXECUTION_PROOF_SCHEMA"); // Altair From 3323b185135313bef7b0fb34569b1c5f176d2861 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 16:31:06 +1000 Subject: [PATCH 15/98] add tests for the cli options Signed-off-by: Gabriel Fukushima --- .../teku/cli/options/ZkChainOptionsTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 teku/src/test/java/tech/pegasys/teku/cli/options/ZkChainOptionsTest.java 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 new file mode 100644 index 00000000000..10245214888 --- /dev/null +++ b/teku/src/test/java/tech/pegasys/teku/cli/options/ZkChainOptionsTest.java @@ -0,0 +1,28 @@ +package tech.pegasys.teku.cli.options; + +import org.junit.jupiter.api.Test; +import tech.pegasys.teku.cli.AbstractBeaconNodeCommandTest; +import tech.pegasys.teku.config.TekuConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +class ZkChainOptionsTest extends AbstractBeaconNodeCommandTest { + + @Test + public void statelessValidationEnabled_true() { + final TekuConfiguration config = getTekuConfigurationFromArguments("--Xstateless-validation-enabled=true"); + assertThat(config.zkChainConfiguration().isStatelessValidationEnabled()).isTrue(); + } + + @Test + public void generateExecutionProofsEnabled_true() { + final TekuConfiguration config = getTekuConfigurationFromArguments("--Xgenerate-execution-proofs-enabled=true"); + assertThat(config.zkChainConfiguration().isGenerateExecutionProofsEnabled()).isTrue(); + } + + @Test + public void statelessMinProofsRequired_receivesCorrectValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments("--Xstateless-min-proofs-required=2"); + assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(2); + } +} \ No newline at end of file From 934330f37f5fdbaa5a15a1049bec923e272a9a91 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 16:31:35 +1000 Subject: [PATCH 16/98] spotless Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 3 -- .../execution/ExecutionProofSchema.java | 50 +++++++++++------- .../registry/SchemaRegistryBuilder.java | 5 +- .../spec/schemas/registry/SchemaTypes.java | 1 - .../teku/cli/options/ZkChainOptionsTest.java | 52 ++++++++++++------- 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 29fd84c2644..0b555c87b8e 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -15,12 +15,9 @@ import tech.pegasys.teku.infrastructure.ssz.SszVector; import tech.pegasys.teku.infrastructure.ssz.containers.Container4; -import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; -import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; -import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProof diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index 075cb6ac612..98b2259964a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.SszVector; @@ -10,25 +23,24 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProofSchema - extends ContainerSchema4< - ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { + extends ContainerSchema4> { - public ExecutionProofSchema() { - super( - "ExecutionProof", - namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), - namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema( - "proof_data", - SszVectorSchema.create( - SszPrimitiveSchemas.BYTE_SCHEMA, - 65536)) // Assuming max size of proof_data is 65536 bytes + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema( + "proof_data", + SszVectorSchema.create( + SszPrimitiveSchemas.BYTE_SCHEMA, + 65536)) // Assuming max size of proof_data is 65536 bytes ); - } + } - @Override - public ExecutionProof createFromBackingNode(final TreeNode node) { - return new ExecutionProof(this, node); - } -} \ No newline at end of file + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 9cf96c7333b..74e57750eee 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -132,7 +132,6 @@ import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationDataSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadHeaderSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; @@ -881,9 +880,7 @@ private static SchemaProvider createStatusMessageSchemaProvider() { private static SchemaProvider createExecutionProofSchemaProvider() { return providerBuilder(EXECUTION_PROOF_SCHEMA) - .withCreator( - ELECTRA, - (registry, specConfig, schemaName) -> new ExecutionProofSchema()) + .withCreator(ELECTRA, (registry, specConfig, schemaName) -> new ExecutionProofSchema()) .build(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index 5af7989929b..23e66c18d46 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -53,7 +53,6 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.WithdrawalSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; 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 10245214888..9e8234e7336 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 @@ -1,28 +1,44 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.cli.options; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.jupiter.api.Test; import tech.pegasys.teku.cli.AbstractBeaconNodeCommandTest; import tech.pegasys.teku.config.TekuConfiguration; -import static org.assertj.core.api.Assertions.assertThat; - class ZkChainOptionsTest extends AbstractBeaconNodeCommandTest { - @Test - public void statelessValidationEnabled_true() { - final TekuConfiguration config = getTekuConfigurationFromArguments("--Xstateless-validation-enabled=true"); - assertThat(config.zkChainConfiguration().isStatelessValidationEnabled()).isTrue(); - } + @Test + public void statelessValidationEnabled_true() { + final TekuConfiguration config = + getTekuConfigurationFromArguments("--Xstateless-validation-enabled=true"); + assertThat(config.zkChainConfiguration().isStatelessValidationEnabled()).isTrue(); + } - @Test - public void generateExecutionProofsEnabled_true() { - final TekuConfiguration config = getTekuConfigurationFromArguments("--Xgenerate-execution-proofs-enabled=true"); - assertThat(config.zkChainConfiguration().isGenerateExecutionProofsEnabled()).isTrue(); - } + @Test + public void generateExecutionProofsEnabled_true() { + final TekuConfiguration config = + getTekuConfigurationFromArguments("--Xgenerate-execution-proofs-enabled=true"); + assertThat(config.zkChainConfiguration().isGenerateExecutionProofsEnabled()).isTrue(); + } - @Test - public void statelessMinProofsRequired_receivesCorrectValue() { - final TekuConfiguration config = getTekuConfigurationFromArguments("--Xstateless-min-proofs-required=2"); - assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(2); - } -} \ No newline at end of file + @Test + public void statelessMinProofsRequired_receivesCorrectValue() { + final TekuConfiguration config = + getTekuConfigurationFromArguments("--Xstateless-min-proofs-required=2"); + assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(2); + } +} From fe3c4ff097a895561c37e9834927fe0fb0bc4c7f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 1 Sep 2025 14:37:41 +1000 Subject: [PATCH 17/98] ExecutionProof container for ZkEVM L2 Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java new file mode 100644 index 00000000000..8308518f2c2 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -0,0 +1,62 @@ +package tech.pegasys.teku.spec.datastructures.execution; + +import tech.pegasys.teku.infrastructure.ssz.SszVector; +import tech.pegasys.teku.infrastructure.ssz.containers.Container4; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; +import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; +import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; + +public class ExecutionProof extends Container4> { + + public static class ExecutionProofSchema extends ContainerSchema4> { + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("proof_data", SszVectorSchema.create(SszPrimitiveSchemas.BYTE_SCHEMA, 65536)) // Assuming max size of proof_data is 65536 bytes + ); + } + + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); + } + + } + + public static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); + + private ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { + super(type, node); + } + + public ExecutionProof( + final SszBytes32 blockHash, + final SszUInt64 subnetId, + final SszUInt64 version, + final SszVector proofData) { + super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); + } + + + public SszBytes32 getBlockHash() { + return getField0(); + } + public SszUInt64 getSubnetId() { + return getField1(); + } + + public SszUInt64 getVersion() { + return getField2(); + } + + public SszVector getProofData() { + return getField3(); + } +} From e9aa75f33ca3c8a26a30f4cb6b60d681fbe73d5f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 2 Sep 2025 16:30:12 +1000 Subject: [PATCH 18/98] separate schema from class Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 94 +++++++++---------- .../execution/ExecutionProofSchema.java | 34 +++++++ .../registry/SchemaRegistryBuilder.java | 12 +++ .../spec/schemas/registry/SchemaTypes.java | 4 + 4 files changed, 95 insertions(+), 49 deletions(-) create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 8308518f2c2..29fd84c2644 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.SszVector; @@ -10,53 +23,36 @@ import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; -public class ExecutionProof extends Container4> { - - public static class ExecutionProofSchema extends ContainerSchema4> { - public ExecutionProofSchema() { - super( - "ExecutionProof", - namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), - namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("proof_data", SszVectorSchema.create(SszPrimitiveSchemas.BYTE_SCHEMA, 65536)) // Assuming max size of proof_data is 65536 bytes - ); - } - - @Override - public ExecutionProof createFromBackingNode(final TreeNode node) { - return new ExecutionProof(this, node); - } - - } - - public static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); - - private ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { - super(type, node); - } - - public ExecutionProof( - final SszBytes32 blockHash, - final SszUInt64 subnetId, - final SszUInt64 version, - final SszVector proofData) { - super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); - } - - - public SszBytes32 getBlockHash() { - return getField0(); - } - public SszUInt64 getSubnetId() { - return getField1(); - } - - public SszUInt64 getVersion() { - return getField2(); - } - - public SszVector getProofData() { - return getField3(); - } +public class ExecutionProof + extends Container4> { + + private static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); + + public ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { + super(type, node); + } + + public ExecutionProof( + final SszBytes32 blockHash, + final SszUInt64 subnetId, + final SszUInt64 version, + final SszVector proofData) { + super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); + } + + public SszBytes32 getBlockHash() { + return getField0(); + } + + public SszUInt64 getSubnetId() { + return getField1(); + } + + public SszUInt64 getVersion() { + return getField2(); + } + + public SszVector getProofData() { + return getField3(); + } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java new file mode 100644 index 00000000000..075cb6ac612 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -0,0 +1,34 @@ +package tech.pegasys.teku.spec.datastructures.execution; + +import tech.pegasys.teku.infrastructure.ssz.SszVector; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; +import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; +import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; + +public class ExecutionProofSchema + extends ContainerSchema4< + ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { + + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema( + "proof_data", + SszVectorSchema.create( + SszPrimitiveSchemas.BYTE_SCHEMA, + 65536)) // Assuming max size of proof_data is 65536 bytes + ); + } + + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); + } +} \ No newline at end of file diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index d49f7820381..9cf96c7333b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -54,6 +54,7 @@ import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_AND_BLOBS_CELL_BUNDLE_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_HEADER_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_SCHEMA; +import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PROOF_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_REQUESTS_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.HISTORICAL_BATCH_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.HISTORICAL_SUMMARIES_SCHEMA; @@ -131,6 +132,8 @@ import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationDataSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadHeaderSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.ExecutionPayloadHeaderSchemaCapella; @@ -238,6 +241,7 @@ public static SchemaRegistryBuilder create() { .addProvider(createConsolidationRequestSchemaProvider()) .addProvider(createExecutionRequestsSchemaProvider()) .addProvider(createSingleAttestationSchemaProvider()) + .addProvider(createExecutionProofSchemaProvider()) // FULU .addProvider(createCellSchemaProvider()) @@ -875,6 +879,14 @@ private static SchemaProvider createStatusMessageSchemaProvider() { .build(); } + private static SchemaProvider createExecutionProofSchemaProvider() { + return providerBuilder(EXECUTION_PROOF_SCHEMA) + .withCreator( + ELECTRA, + (registry, specConfig, schemaName) -> new ExecutionProofSchema()) + .build(); + } + private static long getMaxValidatorsPerAttestationPhase0(final SpecConfig specConfig) { return specConfig.getMaxValidatorsPerCommittee(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index 64c26afcfcb..5af7989929b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -53,6 +53,8 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.WithdrawalSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequestSchema; @@ -121,6 +123,8 @@ public class SchemaTypes { create("METADATA_MESSAGE_SCHEMA"); public static final SchemaId> STATUS_MESSAGE_SCHEMA = create("STATUS_MESSAGE_SCHEMA"); + public static final SchemaId EXECUTION_PROOF_SCHEMA = + create("EXECUTION_PROOF_SCHEMA"); // Altair From 25a6203127b80e43c3123db0867d3d6bf3e44352 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 3 Sep 2025 11:39:48 +1000 Subject: [PATCH 19/98] Remove containers from this PR Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 55 ------------------- .../execution/ExecutionProofSchema.java | 46 ---------------- .../registry/SchemaRegistryBuilder.java | 8 --- .../spec/schemas/registry/SchemaTypes.java | 1 - 4 files changed, 110 deletions(-) delete mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java delete mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java deleted file mode 100644 index 0b555c87b8e..00000000000 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2025 - * - * 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. - */ - -package tech.pegasys.teku.spec.datastructures.execution; - -import tech.pegasys.teku.infrastructure.ssz.SszVector; -import tech.pegasys.teku.infrastructure.ssz.containers.Container4; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; -import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; - -public class ExecutionProof - extends Container4> { - - private static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); - - public ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { - super(type, node); - } - - public ExecutionProof( - final SszBytes32 blockHash, - final SszUInt64 subnetId, - final SszUInt64 version, - final SszVector proofData) { - super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); - } - - public SszBytes32 getBlockHash() { - return getField0(); - } - - public SszUInt64 getSubnetId() { - return getField1(); - } - - public SszUInt64 getVersion() { - return getField2(); - } - - public SszVector getProofData() { - return getField3(); - } -} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java deleted file mode 100644 index 98b2259964a..00000000000 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2025 - * - * 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. - */ - -package tech.pegasys.teku.spec.datastructures.execution; - -import tech.pegasys.teku.infrastructure.ssz.SszVector; -import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; -import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; -import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; -import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; - -public class ExecutionProofSchema - extends ContainerSchema4> { - - public ExecutionProofSchema() { - super( - "ExecutionProof", - namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), - namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema( - "proof_data", - SszVectorSchema.create( - SszPrimitiveSchemas.BYTE_SCHEMA, - 65536)) // Assuming max size of proof_data is 65536 bytes - ); - } - - @Override - public ExecutionProof createFromBackingNode(final TreeNode node) { - return new ExecutionProof(this, node); - } -} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 74e57750eee..7029376b1dd 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -132,7 +132,6 @@ import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationDataSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadHeaderSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.ExecutionPayloadHeaderSchemaCapella; @@ -240,7 +239,6 @@ public static SchemaRegistryBuilder create() { .addProvider(createConsolidationRequestSchemaProvider()) .addProvider(createExecutionRequestsSchemaProvider()) .addProvider(createSingleAttestationSchemaProvider()) - .addProvider(createExecutionProofSchemaProvider()) // FULU .addProvider(createCellSchemaProvider()) @@ -878,12 +876,6 @@ private static SchemaProvider createStatusMessageSchemaProvider() { .build(); } - private static SchemaProvider createExecutionProofSchemaProvider() { - return providerBuilder(EXECUTION_PROOF_SCHEMA) - .withCreator(ELECTRA, (registry, specConfig, schemaName) -> new ExecutionProofSchema()) - .build(); - } - private static long getMaxValidatorsPerAttestationPhase0(final SpecConfig specConfig) { return specConfig.getMaxValidatorsPerCommittee(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index 23e66c18d46..337b3f5d5cc 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -53,7 +53,6 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.WithdrawalSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequestSchema; From 06d88356881d564c081dca68e31bebce35995ea5 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 3 Sep 2025 11:40:03 +1000 Subject: [PATCH 20/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/spec/schemas/registry/SchemaRegistryBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 7029376b1dd..d49f7820381 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -54,7 +54,6 @@ import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_AND_BLOBS_CELL_BUNDLE_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_HEADER_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PAYLOAD_SCHEMA; -import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PROOF_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_REQUESTS_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.HISTORICAL_BATCH_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.HISTORICAL_SUMMARIES_SCHEMA; From 7e3fffcbf69711a3e766e0e6ef6311bcafcd31c6 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 3 Sep 2025 11:41:08 +1000 Subject: [PATCH 21/98] remove execution proof schema Signed-off-by: Gabriel Fukushima --- .../tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index 337b3f5d5cc..64c26afcfcb 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -121,8 +121,6 @@ public class SchemaTypes { create("METADATA_MESSAGE_SCHEMA"); public static final SchemaId> STATUS_MESSAGE_SCHEMA = create("STATUS_MESSAGE_SCHEMA"); - public static final SchemaId EXECUTION_PROOF_SCHEMA = - create("EXECUTION_PROOF_SCHEMA"); // Altair From 58fc87964a23ddbdaf0a2564197bd2ed09c2c17a Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 3 Sep 2025 11:45:20 +1000 Subject: [PATCH 22/98] add default values test Signed-off-by: Gabriel Fukushima --- .../teku/cli/options/ZkChainOptionsTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 9e8234e7336..2f798fb023a 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 @@ -41,4 +41,23 @@ public void statelessMinProofsRequired_receivesCorrectValue() { getTekuConfigurationFromArguments("--Xstateless-min-proofs-required=2"); assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(2); } + + @Test + public void statelessMinProofsRequired_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(1); + } + + @Test + public void statelessValidationEnabled_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().isStatelessValidationEnabled()).isFalse(); + } + + @Test + public void generateExecutionProofsEnabled_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().isGenerateExecutionProofsEnabled()).isFalse(); + } + } From 5be132d7e8822ecae9399b54245c3bad4261502b Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 3 Sep 2025 11:45:30 +1000 Subject: [PATCH 23/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/cli/options/ZkChainOptionsTest.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) 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 2f798fb023a..414a8595061 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 @@ -43,21 +43,20 @@ public void statelessMinProofsRequired_receivesCorrectValue() { } @Test - public void statelessMinProofsRequired_receivesDefaultValue() { - final TekuConfiguration config = getTekuConfigurationFromArguments(); - assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(1); - } - - @Test - public void statelessValidationEnabled_receivesDefaultValue() { - final TekuConfiguration config = getTekuConfigurationFromArguments(); - assertThat(config.zkChainConfiguration().isStatelessValidationEnabled()).isFalse(); - } - - @Test - public void generateExecutionProofsEnabled_receivesDefaultValue() { - final TekuConfiguration config = getTekuConfigurationFromArguments(); - assertThat(config.zkChainConfiguration().isGenerateExecutionProofsEnabled()).isFalse(); - } + public void statelessMinProofsRequired_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().getStatelessMinProofsRequired()).isEqualTo(1); + } + + @Test + public void statelessValidationEnabled_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().isStatelessValidationEnabled()).isFalse(); + } + @Test + public void generateExecutionProofsEnabled_receivesDefaultValue() { + final TekuConfiguration config = getTekuConfigurationFromArguments(); + assertThat(config.zkChainConfiguration().isGenerateExecutionProofsEnabled()).isFalse(); + } } From cbf2371755743c033adbb665979ae244726ccd31 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 4 Sep 2025 10:56:25 +1000 Subject: [PATCH 24/98] subnets boilerplate Signed-off-by: Gabriel Fukushima --- .../networking/eth2/ActiveEth2P2PNetwork.java | 13 ++-- .../teku/networking/eth2/Eth2P2PNetwork.java | 4 +- .../eth2/Eth2P2PNetworkBuilder.java | 8 ++- .../ExecutionProofSubnetSubscriber.java | 71 +++++++++++++++++++ .../ExecutionProofSubnetTopicProvider.java | 23 ++++++ .../subnets/PeerSubnetSubscriptions.java | 61 ++++++++++++++-- .../eth2/gossip/subnets/SubnetScorer.java | 27 ++++++- .../eth2/gossip/topics/GossipTopics.java | 5 ++ .../p2p/discovery/DiscoveryPeer.java | 9 ++- .../p2p/discovery/discv5/DiscV5Service.java | 1 + .../discovery/discv5/NodeRecordConverter.java | 5 +- 11 files changed, 205 insertions(+), 22 deletions(-) create mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java create mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java index 829d8db4607..b650cf6e043 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java @@ -98,6 +98,7 @@ public ActiveEth2P2PNetwork( final SubnetSubscriptionService attestationSubnetService, final SubnetSubscriptionService syncCommitteeSubnetService, final SubnetSubscriptionService dataColumnSidecarSubnetService, + final SubnetSubscriptionService executionProofSubnetService, final GossipEncoding gossipEncoding, final GossipConfigurator gossipConfigurator, final ProcessedAttestationSubscriptionProvider processedAttestationSubscriptionProvider, @@ -357,18 +358,18 @@ public void subscribeToDataColumnSidecarSubnetId(final int subnetId) { dataColumnSidecarSubnetService.addSubscription(subnetId); } + @Override + public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) { + gossipForkManager.unsubscribeFromDataColumnSidecarSubnetId(subnetId); + dataColumnSidecarSubnetService.removeSubscription(subnetId); + } + @Override public void subscribeToExecutionProofSubnetId(final int subnetId) { gossipForkManager.subscribeToExecutionProofSubnetId(subnetId); executionProofSubnetService.addSubscription(subnetId); } - @Override - public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) { - gossipForkManager.unsubscribeFromDataColumnSidecarSubnetId(subnetId); - dataColumnSidecarSubnetService.removeSubscription(subnetId); - } - @Override public void unsubscribeFromExecutionProofSubnetId(final int subnetId) { gossipForkManager.unsubscribeFromExecutionProofSubnetId(subnetId); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java index 59c407dbb77..33fb8b9ea10 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetwork.java @@ -40,12 +40,12 @@ public interface Eth2P2PNetwork extends P2PNetwork { void unsubscribeFromSyncCommitteeSubnetId(int subnetId); - void subscribeToExecutionProofSubnetId(int subnetId); - void subscribeToDataColumnSidecarSubnetId(int subnetId); void unsubscribeFromDataColumnSidecarSubnetId(int subnetId); + void subscribeToExecutionProofSubnetId(int subnetId); + void unsubscribeFromExecutionProofSubnetId(int subnetId); MetadataMessage getMetadata(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 97e5a7dde84..1486a463b01 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -167,6 +167,7 @@ public Eth2P2PNetwork build() { final SubnetSubscriptionService syncCommitteeSubnetService = new SubnetSubscriptionService(); final SubnetSubscriptionService dataColumnSidecarSubnetService = new SubnetSubscriptionService(); + final SubnetSubscriptionService executionProofSubnetService = new SubnetSubscriptionService(); final DiscoveryNodeIdExtractor discoveryNodeIdExtractor = new LibP2PDiscoveryNodeIdExtractor(); final RpcEncoding rpcEncoding = RpcEncoding.createSszSnappyEncoding(spec.getNetworkingConfig().getMaxPayloadSize()); @@ -215,7 +216,7 @@ public Eth2P2PNetwork build() { final GossipEncoding gossipEncoding = config.getGossipEncoding(); // Build core network and inject eth2 handlers final DiscoveryNetwork network = - buildNetwork(gossipEncoding, syncCommitteeSubnetService, dataColumnSidecarSubnetService); + buildNetwork(gossipEncoding, syncCommitteeSubnetService, dataColumnSidecarSubnetService, executionProofSubnetService); final GossipForkManager gossipForkManager = buildGossipForkManager(gossipEncoding, network); @@ -230,6 +231,7 @@ public Eth2P2PNetwork build() { attestationSubnetService, syncCommitteeSubnetService, dataColumnSidecarSubnetService, + executionProofSubnetService, gossipEncoding, config.getGossipConfigurator(), processedAttestationSubscriptionProvider, @@ -488,7 +490,8 @@ private GossipForkSubscriptions createBpoSubscriptions( protected DiscoveryNetwork buildNetwork( final GossipEncoding gossipEncoding, final SubnetSubscriptionService syncCommitteeSubnetService, - final SubnetSubscriptionService dataColumnSidecarSubnetService) { + final SubnetSubscriptionService dataColumnSidecarSubnetService, + final SubnetSubscriptionService executionProofSubnetService) { final PeerPools peerPools = new PeerPools(); final ReputationManager reputationManager = new DefaultReputationManager( @@ -567,6 +570,7 @@ protected DiscoveryNetwork buildNetwork( syncCommitteeSubnetService, dataColumnSidecarSubnetTopicProvider, dataColumnSidecarSubnetService, + executionProofSubnetService, config.getTargetSubnetSubscriberCount(), subnetPeerCountGauge), reputationManager, diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java new file mode 100644 index 00000000000..8c29cfa37a0 --- /dev/null +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java @@ -0,0 +1,71 @@ +package tech.pegasys.teku.networking.eth2.gossip.subnets; + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import org.apache.tuweni.units.bigints.UInt256; +import tech.pegasys.teku.ethereum.events.SlotEventsChannel; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.networking.eth2.Eth2P2PNetwork; +import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; +import tech.pegasys.teku.spec.Spec; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; + +import static java.util.stream.Collectors.toList; + +public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { + private final Eth2P2PNetwork eth2P2PNetwork; + private final ZkChainConfiguration zkChainConfiguration; + private final UInt256 nodeId; + private final Spec spec; + + private IntSet currentSubscribedSubnets = IntSet.of(); + private UInt64 lastEpoch = UInt64.MAX_VALUE; + public static final UInt64 MAX_EXECUTION_PROOF_SUBNETS = UInt64.valueOf(8); + + public ExecutionProofSubnetSubscriber( + final Spec spec, + final Eth2P2PNetwork eth2P2PNetwork, + final UInt256 nodeId, + final ZkChainConfiguration zkChainConfiguration) { + this.spec = spec; + this.eth2P2PNetwork = eth2P2PNetwork; + this.nodeId = nodeId; + this.zkChainConfiguration = zkChainConfiguration; + } + + private void subscribeToSubnets(final Collection newSubscriptions) { + + IntOpenHashSet newSubscriptionsSet = new IntOpenHashSet(newSubscriptions); + + for (int oldSubnet : currentSubscribedSubnets) { + if (!newSubscriptionsSet.contains(oldSubnet)) { + eth2P2PNetwork.unsubscribeFromExecutionProofSubnetId(oldSubnet); + } + } + + for (int newSubnet : newSubscriptionsSet) { + if (!currentSubscribedSubnets.contains(newSubnet)) { + eth2P2PNetwork.subscribeToExecutionProofSubnetId(newSubnet); + } + } + + currentSubscribedSubnets = newSubscriptionsSet; + } + + private void onEpoch(final UInt64 epoch) { + subscribeToSubnets(IntStream.range(0,MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); + } + + @Override + public synchronized void onSlot(final UInt64 slot) { + UInt64 epoch = spec.computeEpochAtSlot(slot); + if (!epoch.equals(lastEpoch)) { + lastEpoch = epoch; + onEpoch(epoch); + } + } +} diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java new file mode 100644 index 00000000000..19b4bc5609c --- /dev/null +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java @@ -0,0 +1,23 @@ +package tech.pegasys.teku.networking.eth2.gossip.subnets; + +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; +import tech.pegasys.teku.storage.client.RecentChainData; + +import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopics.getExecutionProofSubnetTopic; + +public class ExecutionProofSubnetTopicProvider { + private final RecentChainData recentChainData; + private final GossipEncoding gossipEncoding; + + public ExecutionProofSubnetTopicProvider( + final RecentChainData recentChainData, final GossipEncoding gossipEncoding) { + this.recentChainData = recentChainData; + this.gossipEncoding = gossipEncoding; + } + + public String getTopicForSubnet(final int subnetId) { + final Bytes4 forkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); + return getExecutionProofSubnetTopic(forkDigest, subnetId, gossipEncoding); + } +} diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index b951ec0cf18..2d7774c2f26 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -45,6 +45,7 @@ public class PeerSubnetSubscriptions { private final SubnetSubscriptions attestationSubnetSubscriptions; private final SubnetSubscriptions syncCommitteeSubnetSubscriptions; private final SubnetSubscriptions dataColumnSidecarSubnetSubscriptions; + private final SubnetSubscriptions executionProofSubnetSubscriptions; private final NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator; private final int targetSubnetSubscriberCount; @@ -53,11 +54,13 @@ private PeerSubnetSubscriptions( final SubnetSubscriptions attestationSubnetSubscriptions, final SubnetSubscriptions syncCommitteeSubnetSubscriptions, final SubnetSubscriptions dataColumnSidecarSubnetSubscriptions, + final SubnetSubscriptions executionProofSubnetSubscriptions, final NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator, final int targetSubnetSubscriberCount) { this.attestationSubnetSubscriptions = attestationSubnetSubscriptions; this.syncCommitteeSubnetSubscriptions = syncCommitteeSubnetSubscriptions; this.dataColumnSidecarSubnetSubscriptions = dataColumnSidecarSubnetSubscriptions; + this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; this.nodeIdToDataColumnSidecarSubnetsCalculator = nodeIdToDataColumnSidecarSubnetsCalculator; this.targetSubnetSubscriberCount = targetSubnetSubscriberCount; } @@ -71,6 +74,8 @@ public static PeerSubnetSubscriptions create( final SubnetSubscriptionService syncCommitteeSubnetService, final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider, final SubnetSubscriptionService dataColumnSidecarSubnetService, + final ExecutionProofSubnetTopicProvider exeecutionProofSubnetTopicProvider, + final SubnetSubscriptionService executionProofSubnetService, final int targetSubnetSubscriberCount, final SettableLabelledGauge subnetPeerCountGauge) { final Map> subscribersByTopic = network.getSubscribersByTopic(); @@ -85,7 +90,7 @@ public static PeerSubnetSubscriptions create( .orElse(1); final PeerSubnetSubscriptions subscriptions = - builder(currentSchemaDefinitions, SszBitvectorSchema.create(dataColumnSidecarSubnetCount)) + builder(currentSchemaDefinitions, SszBitvectorSchema.create(dataColumnSidecarSubnetCount), SszBitvectorSchema.create(ExecutionProofSubnetSubscriber.MAX_EXECUTION_PROOF_SUBNETS.intValue())) .targetSubnetSubscriberCount(targetSubnetSubscriberCount) .nodeIdToDataColumnSidecarSubnetsCalculator(nodeIdToDataColumnSidecarSubnetsCalculator) .attestationSubnetSubscriptions( @@ -133,6 +138,22 @@ public static PeerSubnetSubscriptions create( Collections.emptySet()) .forEach(subscriber -> b.addSubscriber(columnSubnet, subscriber)); })) + .executionProofSubnetSubscriptions( + b -> + executionProofSubnetService + .getSubnets() + .forEach( + execSubnet -> { + b.addRelevantSubnet(execSubnet); + // Execution payloads are gossiped on the same topic as + // data column sidecars + subscribersByTopic + .getOrDefault( + exeecutionProofSubnetTopicProvider.getTopicForSubnet( + execSubnet), + Collections.emptySet()) + .forEach(subscriber -> b.addSubscriber(execSubnet, subscriber)); + })) .build(); updateMetrics(currentSchemaDefinitions, subnetPeerCountGauge, subscriptions); return subscriptions; @@ -170,15 +191,17 @@ private static IntStream streamAllSyncCommitteeSubnetIds( static Builder builder( final SchemaDefinitionsSupplier currentSchemaDefinitions, - final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { - return new Builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema); + final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, + final SszBitvectorSchema executionProofSubnetSubscription) { + return new Builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema, executionProofSubnetSubscription); } @VisibleForTesting static PeerSubnetSubscriptions createEmpty( final SchemaDefinitionsSupplier currentSchemaDefinitions, - final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { - return builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema) + final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, + final SszBitvectorSchema executionProofSubnetSubscription) { + return builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema, executionProofSubnetSubscription) .nodeIdToDataColumnSidecarSubnetsCalculator(NodeIdToDataColumnSidecarSubnetsCalculator.NOOP) .build(); } @@ -195,6 +218,10 @@ public int getSubscriberCountForDataColumnSidecarSubnet(final int subnetId) { return dataColumnSidecarSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); } + public int getSubscriberCountForExecutionProofSubnet(final int subnetId) { + return executionProofSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); + } + public SszBitvector getAttestationSubnetSubscriptions(final NodeId peerId) { return attestationSubnetSubscriptions.getSubnetSubscriptions(peerId); } @@ -207,6 +234,10 @@ public SszBitvector getDataColumnSidecarSubnetSubscriptions(final NodeId peerId) return dataColumnSidecarSubnetSubscriptions.getSubnetSubscriptions(peerId); } + public Optional getExecutionProofSubnetSubscriptions(final NodeId peerId) { + return Optional.of(executionProofSubnetSubscriptions.getSubnetSubscriptions(peerId)); + } + public SszBitvector getDataColumnSidecarSubnetSubscriptionsByNodeId( final UInt256 peerId, final Optional custodySubnetCount) { return nodeIdToDataColumnSidecarSubnetsCalculator @@ -226,6 +257,10 @@ public boolean isDataColumnSidecarSubnetRelevant(final int subnetId) { return dataColumnSidecarSubnetSubscriptions.isSubnetRelevant(subnetId); } + public boolean isExecutionProofSubnetRelevant(final int subnetId) { + return executionProofSubnetSubscriptions.isSubnetRelevant(subnetId); + } + public PeerScorer createScorer() { return SubnetScorer.create(this); } @@ -244,7 +279,8 @@ private OptionalInt getMinSubscriberCount() { List.of( attestationSubnetSubscriptions.getMinSubscriberCount(), syncCommitteeSubnetSubscriptions.getMinSubscriberCount(), - dataColumnSidecarSubnetSubscriptions.getMinSubscriberCount())); + dataColumnSidecarSubnetSubscriptions.getMinSubscriberCount(), + executionProofSubnetSubscriptions.getMinSubscriberCount())); } private static OptionalInt optionalMin(final List optionalInts) { @@ -351,18 +387,22 @@ public static class Builder { private final SubnetSubscriptions.Builder attestationSubnetSubscriptions; private final SubnetSubscriptions.Builder syncCommitteeSubnetSubscriptions; private final SubnetSubscriptions.Builder dataColumnSidecarSubnetSubscriptions; + private final SubnetSubscriptions.Builder executionProofSubnetSubscriptions; private NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator; private int targetSubnetSubscriberCount = 2; private Builder( final SchemaDefinitionsSupplier currentSchemaDefinitions, - final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { + final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, + final SszBitvectorSchema executionProofSubnetSubscription) { attestationSubnetSubscriptions = SubnetSubscriptions.builder(currentSchemaDefinitions.getAttnetsENRFieldSchema()); syncCommitteeSubnetSubscriptions = SubnetSubscriptions.builder(currentSchemaDefinitions.getSyncnetsENRFieldSchema()); dataColumnSidecarSubnetSubscriptions = SubnetSubscriptions.builder(dataColumnSidecarSubnetBitmaskSchema); + executionProofSubnetSubscriptions = + SubnetSubscriptions.builder(executionProofSubnetSubscription); } public PeerSubnetSubscriptions build() { @@ -370,6 +410,7 @@ public PeerSubnetSubscriptions build() { attestationSubnetSubscriptions.build(), syncCommitteeSubnetSubscriptions.build(), dataColumnSidecarSubnetSubscriptions.build(), + executionProofSubnetSubscriptions.build(), nodeIdToDataColumnSidecarSubnetsCalculator, targetSubnetSubscriberCount); } @@ -401,6 +442,12 @@ public Builder dataColumnSidecarSubnetSubscriptions( return this; } + public Builder executionProofSubnetSubscriptions( + final Consumer consumer) { + consumer.accept(executionProofSubnetSubscriptions); + return this; + } + public Builder nodeIdToDataColumnSidecarSubnetsCalculator( final NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator) { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java index 3c333e4e998..7d2dc911bdb 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java @@ -13,6 +13,7 @@ package tech.pegasys.teku.networking.eth2.gossip.subnets; +import java.util.Optional; import java.util.function.IntUnaryOperator; import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitvector; @@ -41,10 +42,13 @@ public int scoreExistingPeer(final NodeId peerId) { peerSubnetSubscriptions.getSyncCommitteeSubscriptions(peerId); final SszBitvector dataColumnSidecarSubscriptions = peerSubnetSubscriptions.getDataColumnSidecarSubnetSubscriptions(peerId); + final Optional executionProofSubscriptions = + peerSubnetSubscriptions.getExecutionProofSubnetSubscriptions(peerId); return score( attSubscriptions, syncCommitteeSubscriptions, dataColumnSidecarSubscriptions, + executionProofSubscriptions, this::scoreSubnetForExistingPeer); } @@ -54,18 +58,21 @@ public int scoreCandidatePeer(final DiscoveryPeer candidate) { candidate.getPersistentAttestationSubnets(), candidate.getSyncCommitteeSubnets(), peerSubnetSubscriptions.getDataColumnSidecarSubnetSubscriptionsByNodeId( - UInt256.fromBytes(candidate.getNodeId()), candidate.getDasCustodySubnetCount())); + UInt256.fromBytes(candidate.getNodeId()), candidate.getDasCustodySubnetCount()), + candidate.getExecutionProofSubnets()); } // @Override public int scoreCandidatePeer( final SszBitvector attSubnetSubscriptions, final SszBitvector syncCommitteeSubnetSubscriptions, - final SszBitvector dataColumnSidecarSubscriptions) { + final SszBitvector dataColumnSidecarSubscriptions, + final Optional executionProofSubnetSubscriptions) { return score( attSubnetSubscriptions, syncCommitteeSubnetSubscriptions, dataColumnSidecarSubscriptions, + executionProofSubnetSubscriptions, this::scoreSubnetForCandidatePeer); } @@ -73,6 +80,7 @@ private int score( final SszBitvector attestationSubnetSubscriptions, final SszBitvector syncCommitteeSubnetSubscriptions, final SszBitvector dataColumnSidecarSubnetSubscriptions, + final Optional executionProofSubnetSubscriptions, final IntUnaryOperator subscriberCountToScore) { final int attestationSubnetScore = attestationSubnetSubscriptions @@ -111,7 +119,20 @@ private int score( }) .sum(); - return attestationSubnetScore + syncCommitteeSubnetScore + dataColumnSidecarSubnetScore; + final int executionProofSubnetScore = + executionProofSubnetSubscriptions.map(executionProof -> + executionProof + .streamAllSetBits() + .filter(peerSubnetSubscriptions::isExecutionProofSubnetRelevant) + .map( + subnetId -> { + int subscriberCount = + peerSubnetSubscriptions.getSubscriberCountForExecutionProofSubnet(subnetId); + return subscriberCountToScore.applyAsInt(subscriberCount); + }) + .sum()).orElse(0); + + return attestationSubnetScore + syncCommitteeSubnetScore + dataColumnSidecarSubnetScore + executionProofSubnetScore; } private int scoreSubnetForExistingPeer(final int subscriberCount) { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java index ac23dbc48bc..1b25e50805e 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java @@ -72,6 +72,11 @@ public static String getDataColumnSidecarSubnetTopic( return getTopic( forkDigest, GossipTopicName.getDataColumnSidecarSubnetTopicName(subnetId), gossipEncoding); } + public static String getExecutionProofSubnetTopic( + final Bytes4 forkDigest, final int subnetId, final GossipEncoding gossipEncoding) { + return getTopic( + forkDigest, GossipTopicName.getExecutionProofSubnetTopicName(subnetId), gossipEncoding); + } public static Set getAllDataColumnSidecarSubnetTopics( final GossipEncoding gossipEncoding, final Bytes4 forkDigest, final Spec spec) { diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java index 8bf0ad64695..06731b2daac 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java @@ -29,6 +29,7 @@ public class DiscoveryPeer { private final Optional enrForkId; private final SszBitvector persistentAttestationSubnets; private final SszBitvector syncCommitteeSubnets; + private final Optional executionProofSubnets; private final Optional dasCustodySubnetCount; private final Optional nextForkDigest; @@ -40,7 +41,8 @@ public DiscoveryPeer( final SszBitvector persistentAttestationSubnets, final SszBitvector syncCommitteeSubnets, final Optional dasCustodySubnetCount, - final Optional nextForkDigest) { + final Optional nextForkDigest, + final Optional executionProofSubnets) { this.publicKey = publicKey; this.nodeId = nodeId; this.nodeAddress = nodeAddress; @@ -49,6 +51,7 @@ public DiscoveryPeer( this.syncCommitteeSubnets = syncCommitteeSubnets; this.dasCustodySubnetCount = dasCustodySubnetCount; this.nextForkDigest = nextForkDigest; + this.executionProofSubnets = executionProofSubnets; } public Bytes getPublicKey() { @@ -75,6 +78,10 @@ public SszBitvector getSyncCommitteeSubnets() { return syncCommitteeSubnets; } + public Optional getExecutionProofSubnets() { + return executionProofSubnets; + } + public Optional getDasCustodySubnetCount() { return dasCustodySubnetCount; } diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java index a4bd609cc2c..eb738ab57a4 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java @@ -292,6 +292,7 @@ public Optional> getDiscoveryAddresses() { currentSchemaDefinitionsSupplier.getAttnetsENRFieldSchema().getDefault(), currentSchemaDefinitionsSupplier.getSyncnetsENRFieldSchema().getDefault(), Optional.empty(), + Optional.empty(), Optional.empty()); return MultiaddrUtil.fromDiscoveryPeerAsUdp(discoveryPeer).toString(); }) diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java index ad6b3b3edd8..15778ee585b 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java @@ -90,6 +90,8 @@ private static DiscoveryPeer socketAddressToDiscoveryPeer( NEXT_FORK_DIGEST_ENR_FIELD, SszPrimitiveSchemas.BYTES4_SCHEMA::sszDeserialize) .map(SszBytes4::get); + //TODO - see how we gonna define this, if we want to use it + final Optional executionProofSubnets = Optional.empty(); return new DiscoveryPeer( ((Bytes) nodeRecord.get(EnrField.PKEY_SECP256K1)), @@ -99,7 +101,8 @@ private static DiscoveryPeer socketAddressToDiscoveryPeer( persistentAttestationSubnets, syncCommitteeSubnets, dasTotalCustodySubnetCount, - nextForkDigest); + nextForkDigest, + executionProofSubnets); } private static Optional parseField( From 2ee1eb0e5c5c07688925859611ed4604b06d4ba0 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 4 Sep 2025 11:06:00 +1000 Subject: [PATCH 25/98] more boilerplate, missing container Signed-off-by: Gabriel Fukushima --- .../networking/eth2/ActiveEth2P2PNetwork.java | 2 ++ .../gossip/ExecutionProofGossipChannel.java | 33 +++++++++++++++++++ .../eth2/gossip/forks/GossipForkManager.java | 8 +++++ .../gossip/forks/GossipForkSubscriptions.java | 4 +++ 4 files changed, 47 insertions(+) create mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java index b650cf6e043..fc1e5db85f4 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java @@ -30,6 +30,7 @@ import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.BlockGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.DataColumnSidecarGossipChannel; +import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.config.Eth2Context; import tech.pegasys.teku.networking.eth2.gossip.config.GossipConfigurator; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; @@ -147,6 +148,7 @@ private synchronized void startup() { eventChannels.subscribe( DataColumnSidecarGossipChannel.class, (sidecar, __) -> gossipForkManager.publishDataColumnSidecar(sidecar)); + eventChannels.subscribe(ExecutionProofGossipChannel.class, gossipForkManager::publishExe); if (recentChainData.isCloseToInSync()) { startGossip(); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java new file mode 100644 index 00000000000..6a8bc65e273 --- /dev/null +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -0,0 +1,33 @@ +/* + * Copyright Consensys Software Inc., 2023 + * + * 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. + */ + +package tech.pegasys.teku.networking.eth2.gossip; + +import tech.pegasys.teku.infrastructure.events.VoidReturningChannelInterface; +import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; +import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; + +import java.util.List; + +public interface ExecutionProofGossipChannel extends VoidReturningChannelInterface { + + ExecutionProofGossipChannel NOOP = (executionProof, origin) -> {}; + + default void publishExecutionProof( + final List executionProofs, final RemoteOrigin origin) { + executionProofs.forEach( + executionProof -> publishExecutionProof(executionProof, origin)); + } + + void publishExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); +} diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 19738920926..415464644f1 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -189,6 +189,14 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo GossipForkSubscriptions::publishDataColumnSidecar); } + public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { + return publishMessageWithFeedback( + executionProof.getSlot(), + executionProof, + "execution proof", + GossipForkSubscriptions::publishExecutionProof); + } + public void publishSyncCommitteeMessage(final ValidatableSyncCommitteeMessage message) { publishMessage( message.getSlot(), diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index c1643e8058b..8c8997b86d6 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -45,6 +45,10 @@ default SafeFuture publishBlobSidecar(final BlobSidecar blobSidecar) { return SafeFuture.COMPLETE; } + default SafeFuture publishExecutionProof(final ExecutionProof executionProof) { + return SafeFuture.COMPLETE; + } + void subscribeToAttestationSubnetId(int subnetId); void unsubscribeFromAttestationSubnetId(int subnetId); From 53abb23ec92157b48aa711ed50483848587c5f99 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 4 Sep 2025 14:50:34 +1000 Subject: [PATCH 26/98] execution proof container changes and test Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 12 +++------ .../execution/ExecutionProofSchema.java | 21 ++++++++++++++- .../schemas/SchemaDefinitionsElectra.java | 10 +++++++ .../spec/schemas/registry/SchemaTypes.java | 6 +++-- .../execution/ExecutionProofPropertyTest.java | 27 +++++++++++++++++++ .../execution/ExecutionProofSupplier.java | 14 ++++++++++ .../teku/spec/util/DataStructureUtil.java | 10 +++++++ 7 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java create mode 100644 ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 29fd84c2644..0f3d344cd9c 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -15,29 +15,25 @@ import tech.pegasys.teku.infrastructure.ssz.SszVector; import tech.pegasys.teku.infrastructure.ssz.containers.Container4; -import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; -import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; -import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProof extends Container4> { - private static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); - - public ExecutionProof(final ExecutionProofSchema type, final TreeNode node) { - super(type, node); + public ExecutionProof(final ExecutionProofSchema schema, final TreeNode node) { + super(schema, node); } public ExecutionProof( + final ExecutionProofSchema schema, final SszBytes32 blockHash, final SszUInt64 subnetId, final SszUInt64 version, final SszVector proofData) { - super(SSZ_SCHEMA, blockHash, subnetId, version, proofData); + super(schema, blockHash, subnetId, version, proofData); } public SszBytes32 getBlockHash() { diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index 075cb6ac612..330f343cba6 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -13,6 +13,12 @@ public class ExecutionProofSchema extends ContainerSchema4< ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { + // Assuming max size of proof_data is 65536 bytes, in reality this should be much less + // since it's just a concat of a couple of hashes plus some extra bytes. + // need to confirm with Kev + static final long MAX_PROOF_DATA_SIZE = 65536; + + public ExecutionProofSchema() { super( "ExecutionProof", @@ -23,12 +29,25 @@ public ExecutionProofSchema() { "proof_data", SszVectorSchema.create( SszPrimitiveSchemas.BYTE_SCHEMA, - 65536)) // Assuming max size of proof_data is 65536 bytes + MAX_PROOF_DATA_SIZE)) ); } + public ExecutionProof create( + final SszBytes32 blockHash, + final SszUInt64 subnetId, + final SszUInt64 version, + final SszVector proofData) { + return new ExecutionProof(this, blockHash, subnetId, version, proofData); + } + @Override public ExecutionProof createFromBackingNode(final TreeNode node) { return new ExecutionProof(this, node); } + + @SuppressWarnings("unchecked") + public SszVectorSchema> getProofDataSchema() { + return (SszVectorSchema>) getFieldSchema3(); + } } \ No newline at end of file diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java index 9abc69de8a9..b8a69300013 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsElectra.java @@ -16,6 +16,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.CONSOLIDATION_REQUEST_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.DEPOSIT_REQUEST_SCHEMA; +import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_PROOF_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.EXECUTION_REQUESTS_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.PENDING_CONSOLIDATIONS_SCHEMA; import static tech.pegasys.teku.spec.schemas.registry.SchemaTypes.PENDING_DEPOSITS_SCHEMA; @@ -28,6 +29,7 @@ import tech.pegasys.teku.spec.config.SpecConfig; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBodyBuilder; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BeaconBlockBodyBuilderElectra; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequestSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsSchema; @@ -57,6 +59,8 @@ public class SchemaDefinitionsElectra extends SchemaDefinitionsDeneb { private final SingleAttestationSchema singleAttestationSchema; + private final ExecutionProofSchema executionProofSchema; + public SchemaDefinitionsElectra(final SchemaRegistry schemaRegistry) { super(schemaRegistry); this.executionRequestsSchema = schemaRegistry.get(EXECUTION_REQUESTS_SCHEMA); @@ -77,6 +81,8 @@ public SchemaDefinitionsElectra(final SchemaRegistry schemaRegistry) { this.pendingConsolidationSchema = (PendingConsolidationSchema) schemaRegistry.get(PENDING_CONSOLIDATIONS_SCHEMA).getElementSchema(); + + this.executionProofSchema = schemaRegistry.get(EXECUTION_PROOF_SCHEMA); } public static SchemaDefinitionsElectra required(final SchemaDefinitions schemaDefinitions) { @@ -149,4 +155,8 @@ public Optional toVersionElectra() { long getMaxValidatorsPerAttestation(final SpecConfig specConfig) { return (long) specConfig.getMaxValidatorsPerCommittee() * specConfig.getMaxCommitteesPerSlot(); } + + public ExecutionProofSchema getExecutionProofSchema() { + return executionProofSchema; + } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index 5af7989929b..cd634591e6b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -123,8 +123,7 @@ public class SchemaTypes { create("METADATA_MESSAGE_SCHEMA"); public static final SchemaId> STATUS_MESSAGE_SCHEMA = create("STATUS_MESSAGE_SCHEMA"); - public static final SchemaId EXECUTION_PROOF_SCHEMA = - create("EXECUTION_PROOF_SCHEMA"); + // Altair @@ -197,6 +196,9 @@ public class SchemaTypes { create("CONSOLIDATION_REQUEST_SCHEMA"); public static final SchemaId SINGLE_ATTESTATION_SCHEMA = create("SINGLE_ATTESTATION_SCHEMA"); + //Move + public static final SchemaId EXECUTION_PROOF_SCHEMA = + create("EXECUTION_PROOF_SCHEMA"); // Fulu public static final SchemaId CELL_SCHEMA = create("CELL_SCHEMA"); diff --git a/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java b/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java new file mode 100644 index 00000000000..0c89a358797 --- /dev/null +++ b/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java @@ -0,0 +1,27 @@ +package tech.pegasys.teku.spec.datastructures.execution; + +import com.fasterxml.jackson.core.JsonProcessingException; +import net.jqwik.api.ForAll; +import net.jqwik.api.Property; +import tech.pegasys.teku.spec.datastructures.execution.versions.capella.Withdrawal; +import tech.pegasys.teku.spec.propertytest.suppliers.execution.ExecutionProofSupplier; +import tech.pegasys.teku.spec.propertytest.suppliers.execution.versions.capella.WithdrawalSupplier; + +import static tech.pegasys.teku.spec.propertytest.util.PropertyTestHelper.assertDeserializeMutatedThrowsExpected; +import static tech.pegasys.teku.spec.propertytest.util.PropertyTestHelper.assertRoundTrip; + +public class ExecutionProofPropertyTest { + + @Property + void roundTrip(@ForAll(supplier = ExecutionProofSupplier.class) final ExecutionProof executionProof) + throws JsonProcessingException { + assertRoundTrip(executionProof); + } + + @Property + void deserializeMutated( + @ForAll(supplier = ExecutionProofSupplier.class) final ExecutionProof executionProof, + @ForAll final int seed) { + assertDeserializeMutatedThrowsExpected(executionProof, seed); + } +} diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java new file mode 100644 index 00000000000..584b671543a --- /dev/null +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java @@ -0,0 +1,14 @@ +package tech.pegasys.teku.spec.propertytest.suppliers.execution; + +import tech.pegasys.teku.spec.SpecMilestone; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.versions.capella.Withdrawal; +import tech.pegasys.teku.spec.propertytest.suppliers.DataStructureUtilSupplier; +import tech.pegasys.teku.spec.util.DataStructureUtil; + +public class ExecutionProofSupplier extends DataStructureUtilSupplier { + public ExecutionProofSupplier() { + super(DataStructureUtil::randomExecutionProof, SpecMilestone.ELECTRA); + } + +} diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index 6be6d8ad649..9da970055c4 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -149,6 +149,8 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadBuilder; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadContext; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.Transaction; import tech.pegasys.teku.spec.datastructures.execution.TransactionSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.Withdrawal; @@ -3090,6 +3092,14 @@ public SszList randomPayloadAttestations() { return randomSszList(schema, this::randomPayloadAttestation, schema.getMaxLength()); } + public ExecutionProof randomExecutionProof() { + final SchemaDefinitionsElectra schemaDefinitionsElectra = + SchemaDefinitionsElectra.required(spec.forMilestone(SpecMilestone.ELECTRA).getSchemaDefinitions()); + final ExecutionProofSchema executionProofSchema = schemaDefinitionsElectra.getExecutionProofSchema(); + return executionProofSchema.create(SszBytes32.of(randomBytes32()), SszUInt64.of(randomUInt64()), + SszUInt64.of(randomUInt64()), randomSszVector(executionProofSchema.getProofDataSchema(),()-> SszByte.of(randomByte()))); + } + private int randomInt(final int origin, final int bound) { return new Random(nextSeed()).ints(origin, bound).findFirst().orElse(0); } From 7373d63d8afa85a7808078fd6638060d9ee44d89 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 5 Sep 2025 11:30:53 +1000 Subject: [PATCH 27/98] spotless Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProofSchema.java | 90 ++++++++++--------- .../registry/SchemaRegistryBuilder.java | 5 +- .../spec/schemas/registry/SchemaTypes.java | 8 +- .../execution/ExecutionProofPropertyTest.java | 44 +++++---- .../execution/ExecutionProofSupplier.java | 21 +++-- .../teku/spec/util/DataStructureUtil.java | 15 ++-- 6 files changed, 107 insertions(+), 76 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index 330f343cba6..a758db2a7df 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.SszVector; @@ -10,44 +23,39 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProofSchema - extends ContainerSchema4< - ExecutionProof, SszBytes32, SszUInt64, SszUInt64, SszVector> { - - // Assuming max size of proof_data is 65536 bytes, in reality this should be much less - // since it's just a concat of a couple of hashes plus some extra bytes. - // need to confirm with Kev - static final long MAX_PROOF_DATA_SIZE = 65536; - - - public ExecutionProofSchema() { - super( - "ExecutionProof", - namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), - namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema( - "proof_data", - SszVectorSchema.create( - SszPrimitiveSchemas.BYTE_SCHEMA, - MAX_PROOF_DATA_SIZE)) - ); - } - - public ExecutionProof create( - final SszBytes32 blockHash, - final SszUInt64 subnetId, - final SszUInt64 version, - final SszVector proofData) { - return new ExecutionProof(this, blockHash, subnetId, version, proofData); - } - - @Override - public ExecutionProof createFromBackingNode(final TreeNode node) { - return new ExecutionProof(this, node); - } - - @SuppressWarnings("unchecked") - public SszVectorSchema> getProofDataSchema() { - return (SszVectorSchema>) getFieldSchema3(); - } -} \ No newline at end of file + extends ContainerSchema4> { + + // Assuming max size of proof_data is 65536 bytes, in reality this should be much less + // since it's just a concat of a couple of hashes plus some extra bytes. + // need to confirm with Kev + static final long MAX_PROOF_DATA_SIZE = 65536; + + public ExecutionProofSchema() { + super( + "ExecutionProof", + namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), + namedSchema( + "proof_data", + SszVectorSchema.create(SszPrimitiveSchemas.BYTE_SCHEMA, MAX_PROOF_DATA_SIZE))); + } + + public ExecutionProof create( + final SszBytes32 blockHash, + final SszUInt64 subnetId, + final SszUInt64 version, + final SszVector proofData) { + return new ExecutionProof(this, blockHash, subnetId, version, proofData); + } + + @Override + public ExecutionProof createFromBackingNode(final TreeNode node) { + return new ExecutionProof(this, node); + } + + @SuppressWarnings("unchecked") + public SszVectorSchema> getProofDataSchema() { + return (SszVectorSchema>) getFieldSchema3(); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java index 9cf96c7333b..74e57750eee 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaRegistryBuilder.java @@ -132,7 +132,6 @@ import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationDataSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationSchema; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadHeaderSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadHeaderSchemaBellatrix; import tech.pegasys.teku.spec.datastructures.execution.versions.bellatrix.ExecutionPayloadSchemaBellatrix; @@ -881,9 +880,7 @@ private static SchemaProvider createStatusMessageSchemaProvider() { private static SchemaProvider createExecutionProofSchemaProvider() { return providerBuilder(EXECUTION_PROOF_SCHEMA) - .withCreator( - ELECTRA, - (registry, specConfig, schemaName) -> new ExecutionProofSchema()) + .withCreator(ELECTRA, (registry, specConfig, schemaName) -> new ExecutionProofSchema()) .build(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index cd634591e6b..b7fbcce86c2 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -53,7 +53,6 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSchema; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.WithdrawalSchema; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequestSchema; @@ -124,7 +123,6 @@ public class SchemaTypes { public static final SchemaId> STATUS_MESSAGE_SCHEMA = create("STATUS_MESSAGE_SCHEMA"); - // Altair // Bellatrix @@ -196,9 +194,9 @@ public class SchemaTypes { create("CONSOLIDATION_REQUEST_SCHEMA"); public static final SchemaId SINGLE_ATTESTATION_SCHEMA = create("SINGLE_ATTESTATION_SCHEMA"); - //Move - public static final SchemaId EXECUTION_PROOF_SCHEMA = - create("EXECUTION_PROOF_SCHEMA"); + // Move + public static final SchemaId EXECUTION_PROOF_SCHEMA = + create("EXECUTION_PROOF_SCHEMA"); // Fulu public static final SchemaId CELL_SCHEMA = create("CELL_SCHEMA"); diff --git a/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java b/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java index 0c89a358797..3f99f57aab5 100644 --- a/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java +++ b/ethereum/spec/src/property-test/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofPropertyTest.java @@ -1,27 +1,39 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.spec.datastructures.execution; +import static tech.pegasys.teku.spec.propertytest.util.PropertyTestHelper.assertDeserializeMutatedThrowsExpected; +import static tech.pegasys.teku.spec.propertytest.util.PropertyTestHelper.assertRoundTrip; + import com.fasterxml.jackson.core.JsonProcessingException; import net.jqwik.api.ForAll; import net.jqwik.api.Property; -import tech.pegasys.teku.spec.datastructures.execution.versions.capella.Withdrawal; import tech.pegasys.teku.spec.propertytest.suppliers.execution.ExecutionProofSupplier; -import tech.pegasys.teku.spec.propertytest.suppliers.execution.versions.capella.WithdrawalSupplier; - -import static tech.pegasys.teku.spec.propertytest.util.PropertyTestHelper.assertDeserializeMutatedThrowsExpected; -import static tech.pegasys.teku.spec.propertytest.util.PropertyTestHelper.assertRoundTrip; public class ExecutionProofPropertyTest { - @Property - void roundTrip(@ForAll(supplier = ExecutionProofSupplier.class) final ExecutionProof executionProof) - throws JsonProcessingException { - assertRoundTrip(executionProof); - } + @Property + void roundTrip( + @ForAll(supplier = ExecutionProofSupplier.class) final ExecutionProof executionProof) + throws JsonProcessingException { + assertRoundTrip(executionProof); + } - @Property - void deserializeMutated( - @ForAll(supplier = ExecutionProofSupplier.class) final ExecutionProof executionProof, - @ForAll final int seed) { - assertDeserializeMutatedThrowsExpected(executionProof, seed); - } + @Property + void deserializeMutated( + @ForAll(supplier = ExecutionProofSupplier.class) final ExecutionProof executionProof, + @ForAll final int seed) { + assertDeserializeMutatedThrowsExpected(executionProof, seed); + } } diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java index 584b671543a..52da502a140 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/propertytest/suppliers/execution/ExecutionProofSupplier.java @@ -1,14 +1,25 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.spec.propertytest.suppliers.execution; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; -import tech.pegasys.teku.spec.datastructures.execution.versions.capella.Withdrawal; import tech.pegasys.teku.spec.propertytest.suppliers.DataStructureUtilSupplier; import tech.pegasys.teku.spec.util.DataStructureUtil; public class ExecutionProofSupplier extends DataStructureUtilSupplier { - public ExecutionProofSupplier() { - super(DataStructureUtil::randomExecutionProof, SpecMilestone.ELECTRA); - } - + public ExecutionProofSupplier() { + super(DataStructureUtil::randomExecutionProof, SpecMilestone.ELECTRA); + } } diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index 9da970055c4..61b41c09160 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -3093,11 +3093,16 @@ public SszList randomPayloadAttestations() { } public ExecutionProof randomExecutionProof() { - final SchemaDefinitionsElectra schemaDefinitionsElectra = - SchemaDefinitionsElectra.required(spec.forMilestone(SpecMilestone.ELECTRA).getSchemaDefinitions()); - final ExecutionProofSchema executionProofSchema = schemaDefinitionsElectra.getExecutionProofSchema(); - return executionProofSchema.create(SszBytes32.of(randomBytes32()), SszUInt64.of(randomUInt64()), - SszUInt64.of(randomUInt64()), randomSszVector(executionProofSchema.getProofDataSchema(),()-> SszByte.of(randomByte()))); + final SchemaDefinitionsElectra schemaDefinitionsElectra = + SchemaDefinitionsElectra.required( + spec.forMilestone(SpecMilestone.ELECTRA).getSchemaDefinitions()); + final ExecutionProofSchema executionProofSchema = + schemaDefinitionsElectra.getExecutionProofSchema(); + return executionProofSchema.create( + SszBytes32.of(randomBytes32()), + SszUInt64.of(randomUInt64()), + SszUInt64.of(randomUInt64()), + randomSszVector(executionProofSchema.getProofDataSchema(), () -> SszByte.of(randomByte()))); } private int randomInt(final int origin, final int bound) { From b052c912545ad54b629a9b7c79b2481c35353934 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 8 Sep 2025 11:10:27 +1000 Subject: [PATCH 28/98] fix container type Signed-off-by: Gabriel Fukushima --- .../datastructures/execution/ExecutionProof.java | 7 ++++--- .../execution/ExecutionProofSchema.java | 12 +++++++----- .../pegasys/teku/spec/util/DataStructureUtil.java | 3 ++- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 0f3d344cd9c..718766e1851 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -14,6 +14,7 @@ package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.SszVector; +import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.containers.Container4; import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; @@ -21,7 +22,7 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProof - extends Container4> { + extends Container4 { public ExecutionProof(final ExecutionProofSchema schema, final TreeNode node) { super(schema, node); @@ -32,7 +33,7 @@ public ExecutionProof( final SszBytes32 blockHash, final SszUInt64 subnetId, final SszUInt64 version, - final SszVector proofData) { + final SszByteList proofData) { super(schema, blockHash, subnetId, version, proofData); } @@ -48,7 +49,7 @@ public SszUInt64 getVersion() { return getField2(); } - public SszVector getProofData() { + public SszByteList getProofData() { return getField3(); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index a758db2a7df..46ab95f4465 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -14,16 +14,18 @@ package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.SszVector; +import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; +import tech.pegasys.teku.infrastructure.ssz.schema.collections.SszByteListSchema; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProofSchema - extends ContainerSchema4> { + extends ContainerSchema4 { // Assuming max size of proof_data is 65536 bytes, in reality this should be much less // since it's just a concat of a couple of hashes plus some extra bytes. @@ -38,14 +40,14 @@ public ExecutionProofSchema() { namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), namedSchema( "proof_data", - SszVectorSchema.create(SszPrimitiveSchemas.BYTE_SCHEMA, MAX_PROOF_DATA_SIZE))); + SszByteListSchema.create(MAX_PROOF_DATA_SIZE))); } public ExecutionProof create( final SszBytes32 blockHash, final SszUInt64 subnetId, final SszUInt64 version, - final SszVector proofData) { + final SszByteList proofData) { return new ExecutionProof(this, blockHash, subnetId, version, proofData); } @@ -55,7 +57,7 @@ public ExecutionProof createFromBackingNode(final TreeNode node) { } @SuppressWarnings("unchecked") - public SszVectorSchema> getProofDataSchema() { - return (SszVectorSchema>) getFieldSchema3(); + public SszByteListSchema getProofDataSchema() { + return (SszByteListSchema) getFieldSchema3(); } } diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index 61b41c09160..b0390d7d730 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -62,6 +62,7 @@ import tech.pegasys.teku.infrastructure.ssz.SszVector; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitvector; +import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.collections.SszBytes32Vector; import tech.pegasys.teku.infrastructure.ssz.collections.SszPrimitiveList; import tech.pegasys.teku.infrastructure.ssz.collections.SszPrimitiveVector; @@ -3102,7 +3103,7 @@ public ExecutionProof randomExecutionProof() { SszBytes32.of(randomBytes32()), SszUInt64.of(randomUInt64()), SszUInt64.of(randomUInt64()), - randomSszVector(executionProofSchema.getProofDataSchema(), () -> SszByte.of(randomByte()))); + executionProofSchema.getProofDataSchema().fromBytes(randomBytes(5))); } private int randomInt(final int origin, final int bound) { From 2a0e93c433328242128e282479068c14550c532b Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 8 Sep 2025 11:13:08 +1000 Subject: [PATCH 29/98] fix comment Signed-off-by: Gabriel Fukushima --- .../tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java index b7fbcce86c2..47a01ce2488 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/SchemaTypes.java @@ -194,7 +194,7 @@ public class SchemaTypes { create("CONSOLIDATION_REQUEST_SCHEMA"); public static final SchemaId SINGLE_ATTESTATION_SCHEMA = create("SINGLE_ATTESTATION_SCHEMA"); - // Move + // Move this when we decide which fork this schema should be under public static final SchemaId EXECUTION_PROOF_SCHEMA = create("EXECUTION_PROOF_SCHEMA"); From 62f53aa41f8502925ba579ec61f6a0fe4843aab9 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 8 Sep 2025 11:13:34 +1000 Subject: [PATCH 30/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/spec/datastructures/execution/ExecutionProof.java | 2 -- .../datastructures/execution/ExecutionProofSchema.java | 7 +------ .../tech/pegasys/teku/spec/util/DataStructureUtil.java | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 718766e1851..9b6e3b0a1a0 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -13,10 +13,8 @@ package tech.pegasys.teku.spec.datastructures.execution; -import tech.pegasys.teku.infrastructure.ssz.SszVector; import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.containers.Container4; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index 46ab95f4465..78b0f766be6 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -13,14 +13,11 @@ package tech.pegasys.teku.spec.datastructures.execution; -import tech.pegasys.teku.infrastructure.ssz.SszVector; import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; -import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; -import tech.pegasys.teku.infrastructure.ssz.schema.SszVectorSchema; import tech.pegasys.teku.infrastructure.ssz.schema.collections.SszByteListSchema; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; @@ -38,9 +35,7 @@ public ExecutionProofSchema() { namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), - namedSchema( - "proof_data", - SszByteListSchema.create(MAX_PROOF_DATA_SIZE))); + namedSchema("proof_data", SszByteListSchema.create(MAX_PROOF_DATA_SIZE))); } public ExecutionProof create( diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index b0390d7d730..b4bd4a8be0b 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -62,7 +62,6 @@ import tech.pegasys.teku.infrastructure.ssz.SszVector; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitvector; -import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.collections.SszBytes32Vector; import tech.pegasys.teku.infrastructure.ssz.collections.SszPrimitiveList; import tech.pegasys.teku.infrastructure.ssz.collections.SszPrimitiveVector; From a1318b9ec5a0c45b372475bffb9ad7fec0be9c5c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 10:12:42 +1000 Subject: [PATCH 31/98] fix config validation Signed-off-by: Gabriel Fukushima --- .../main/java/tech/pegasys/teku/config/TekuConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java b/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java index 09d27c8fa8f..046ded0a600 100644 --- a/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java +++ b/teku/src/main/java/tech/pegasys/teku/config/TekuConfiguration.java @@ -98,7 +98,8 @@ private TekuConfiguration( storeConfig, spec, beaconChainControllerFactory, - metricsConfig); + metricsConfig, + zkChainConfiguration); this.validatorClientConfig = new ValidatorClientConfiguration( validatorConfig, interopConfig, validatorRestApiConfig, spec); From 35f91887d81d397a2aa3f154793e487e35141d05 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 10:12:48 +1000 Subject: [PATCH 32/98] fix config validation Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/services/zkchain/ZkChainConfiguration.java | 3 +++ 1 file changed, 3 insertions(+) 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 c7f4eed7c12..a255334b147 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 @@ -75,6 +75,9 @@ public Builder statelessMinProofsRequired(final int statelessMinProofsRequired) } public ZkChainConfiguration build() { + if(generateExecutionProofsEnabled && !statelessValidationEnabled) { + throw new IllegalStateException("Can't generate execution proofs when statelessValidationEnabled is false"); + } return new ZkChainConfiguration( statelessValidationEnabled, generateExecutionProofsEnabled, statelessMinProofsRequired); } From efa29cfaf463a5c3475abdf3acf540998bcbbd60 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 10:15:46 +1000 Subject: [PATCH 33/98] add zkconfig into beacon chain controller to initialize the subscriber and create gossip validator for now Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/spec/config/Constants.java | 5 ++++ .../networking/eth2/ActiveEth2P2PNetwork.java | 3 ++- .../gossip/ExecutionProofGossipChannel.java | 16 ++++++------ .../eth2/gossip/forks/GossipForkManager.java | 14 +++++++---- .../gossip/forks/GossipForkSubscriptions.java | 1 + .../ExecutionProofSubnetSubscriber.java | 3 ++- .../subnets/PeerSubnetSubscriptions.java | 4 ++- .../beaconchain/BeaconChainConfiguration.java | 8 +++++- .../beaconchain/BeaconChainController.java | 25 +++++++++++++++++++ 9 files changed, 63 insertions(+), 16 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java index 42161003f29..0971dd3af7b 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java @@ -13,6 +13,8 @@ package tech.pegasys.teku.spec.config; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; + import java.time.Duration; public class Constants { @@ -67,4 +69,7 @@ public class Constants { public static final Duration BUILDER_PROPOSAL_DELAY_TOLERANCE = Duration.ofSeconds(1); public static final Duration BUILDER_GET_PAYLOAD_TIMEOUT = Duration.ofSeconds(3); public static final int EPOCHS_PER_VALIDATOR_REGISTRATION_SUBMISSION = 1; + + //ZkChain prototype + public static final UInt64 MAX_EXECUTION_PROOF_SUBNETS = UInt64.valueOf(8); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java index fc1e5db85f4..5cfa5decb40 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java @@ -148,7 +148,8 @@ private synchronized void startup() { eventChannels.subscribe( DataColumnSidecarGossipChannel.class, (sidecar, __) -> gossipForkManager.publishDataColumnSidecar(sidecar)); - eventChannels.subscribe(ExecutionProofGossipChannel.class, gossipForkManager::publishExe); + eventChannels.subscribe(ExecutionProofGossipChannel.class, gossipForkManager::publishExecutionProof); + if (recentChainData.isCloseToInSync()) { startGossip(); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java index 6a8bc65e273..e460a759697 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -13,21 +13,23 @@ package tech.pegasys.teku.networking.eth2.gossip; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.events.ChannelInterface; import tech.pegasys.teku.infrastructure.events.VoidReturningChannelInterface; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; import java.util.List; -public interface ExecutionProofGossipChannel extends VoidReturningChannelInterface { +public interface ExecutionProofGossipChannel extends ChannelInterface { - ExecutionProofGossipChannel NOOP = (executionProof, origin) -> {}; + ExecutionProofGossipChannel NOOP = executionProof -> SafeFuture.COMPLETE; - default void publishExecutionProof( - final List executionProofs, final RemoteOrigin origin) { - executionProofs.forEach( - executionProof -> publishExecutionProof(executionProof, origin)); + default SafeFuture publishExecutionProof( + final List executionProofs) { + return SafeFuture.allOf(executionProofs.stream().map(this::publishExecutionProof)); } - void publishExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + SafeFuture publishExecutionProof(ExecutionProof executionProof); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 415464644f1..4028b0fdf3f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -38,6 +38,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -190,11 +191,13 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo } public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { - return publishMessageWithFeedback( - executionProof.getSlot(), - executionProof, - "execution proof", - GossipForkSubscriptions::publishExecutionProof); + //for now we don't have a slot in the message data (execution proof) to use + // I believe it's safe to just check the current epoch + return publishMessageWithFeedback( + spec.computeStartSlotAtEpoch(currentEpoch.orElseThrow()), + executionProof, + "execution proof", + GossipForkSubscriptions::publishExecutionProof); } public void publishSyncCommitteeMessage(final ValidatableSyncCommitteeMessage message) { @@ -352,6 +355,7 @@ private void startSubscriptions(final GossipForkSubscriptions subscription) { currentAttestationSubnets.forEach(subscription::subscribeToAttestationSubnetId); currentSyncCommitteeSubnets.forEach(subscription::subscribeToSyncCommitteeSubnet); currentDataColumnSidecarSubnets.forEach(subscription::subscribeToDataColumnSidecarSubnet); + currentExecutionProofSubnets.forEach(subscription::subscribeToExecutionProofSubnet); } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index 8c8997b86d6..e560afd57a5 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -20,6 +20,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java index 8c29cfa37a0..8d7513d92a6 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java @@ -15,6 +15,7 @@ import java.util.stream.IntStream; import static java.util.stream.Collectors.toList; +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { private final Eth2P2PNetwork eth2P2PNetwork; @@ -24,7 +25,7 @@ public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { private IntSet currentSubscribedSubnets = IntSet.of(); private UInt64 lastEpoch = UInt64.MAX_VALUE; - public static final UInt64 MAX_EXECUTION_PROOF_SUBNETS = UInt64.valueOf(8); + public ExecutionProofSubnetSubscriber( final Spec spec, diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index 2d7774c2f26..dde94f0f775 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -40,6 +40,8 @@ import tech.pegasys.teku.spec.config.SpecConfigFulu; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsSupplier; +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + public class PeerSubnetSubscriptions { private final SubnetSubscriptions attestationSubnetSubscriptions; @@ -90,7 +92,7 @@ public static PeerSubnetSubscriptions create( .orElse(1); final PeerSubnetSubscriptions subscriptions = - builder(currentSchemaDefinitions, SszBitvectorSchema.create(dataColumnSidecarSubnetCount), SszBitvectorSchema.create(ExecutionProofSubnetSubscriber.MAX_EXECUTION_PROOF_SUBNETS.intValue())) + builder(currentSchemaDefinitions, SszBitvectorSchema.create(dataColumnSidecarSubnetCount), SszBitvectorSchema.create(MAX_EXECUTION_PROOF_SUBNETS.intValue())) .targetSubnetSubscriberCount(targetSubnetSubscriberCount) .nodeIdToDataColumnSidecarSubnetsCalculator(nodeIdToDataColumnSidecarSubnetsCalculator) .attestationSubnetSubscriptions( diff --git a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java index e0cb4f8dad2..7b5b5cf5d77 100644 --- a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java +++ b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java @@ -19,6 +19,7 @@ import tech.pegasys.teku.networking.eth2.P2PConfig; import tech.pegasys.teku.networks.Eth2NetworkConfiguration; import tech.pegasys.teku.services.powchain.PowchainConfiguration; +import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.storage.store.StoreConfig; import tech.pegasys.teku.validator.api.InteropConfig; @@ -36,6 +37,7 @@ public class BeaconChainConfiguration { private final StoreConfig storeConfig; private final PowchainConfiguration powchainConfiguration; private final Spec spec; + private final ZkChainConfiguration zkChainConfiguration; private final BeaconChainControllerFactory beaconChainControllerFactory; private final MetricsConfig metricsConfig; @@ -52,7 +54,8 @@ public BeaconChainConfiguration( final StoreConfig storeConfig, final Spec spec, final BeaconChainControllerFactory beaconChainControllerFactory, - final MetricsConfig metricsConfig) { + final MetricsConfig metricsConfig, + final ZkChainConfiguration zkChainConfiguration) { this.eth2NetworkConfiguration = eth2NetworkConfiguration; this.weakSubjectivityConfig = weakSubjectivityConfig; this.validatorConfig = validatorConfig; @@ -65,6 +68,7 @@ public BeaconChainConfiguration( this.spec = spec; this.beaconChainControllerFactory = beaconChainControllerFactory; this.metricsConfig = metricsConfig; + this.zkChainConfiguration = zkChainConfiguration; } public Spec getSpec() { @@ -114,4 +118,6 @@ public MetricsConfig getMetricsConfig() { public BeaconChainControllerFactory getBeaconChainControllerFactory() { return beaconChainControllerFactory; } + + public ZkChainConfiguration zkChainConfiguration() { return zkChainConfiguration; } } 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 3d90131430f..7aa43637b08 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 @@ -87,10 +87,12 @@ import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.BlockGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.DataColumnSidecarGossipChannel; +import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSubnetsSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSyncCommitteeSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetBackboneSubscriber; +import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.NodeBasedStableSubnetSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.StableSubnetSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubscriptionManager; @@ -106,6 +108,7 @@ import tech.pegasys.teku.service.serviceutils.layout.DataDirLayout; import tech.pegasys.teku.services.executionlayer.ExecutionLayerBlockManagerFactory; import tech.pegasys.teku.services.timer.TimerService; +import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.SpecVersion; @@ -222,6 +225,7 @@ import tech.pegasys.teku.statetransition.validation.BlockGossipValidator; import tech.pegasys.teku.statetransition.validation.BlockValidator; import tech.pegasys.teku.statetransition.validation.DataColumnSidecarGossipValidator; +import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; import tech.pegasys.teku.statetransition.validation.GossipValidationHelper; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; import tech.pegasys.teku.statetransition.validation.ProposerSlashingValidator; @@ -652,6 +656,7 @@ public void initAll() { initOperationsReOrgManager(); initValidatorIndexCacheTracker(); initStoredLatestCanonicalBlockUpdater(); + initKzChain(); } private void initKeyValueStore() { @@ -663,6 +668,26 @@ protected void initExecutionLayer() { executionLayer = eventChannels.getPublisher(ExecutionLayerChannel.class, beaconAsyncRunner); } + protected void initKzChain(){ + ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); + + if(zkConfig.isStatelessValidationEnabled()){ + final ExecutionProofGossipValidator executionProofGossipValidator = + ExecutionProofGossipValidator.create(spec, zkConfig); + + ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = + new ExecutionProofSubnetSubscriber( + spec, + p2pNetwork, + nodeId, + zkConfig); + + + + eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); + } + } + protected void initKzg() { if (spec.isMilestoneSupported(SpecMilestone.DENEB)) { kzg = KZG.getInstance(beaconConfig.eth2NetworkConfig().isRustKzgEnabled()); From 84dd8b740d9edd8257628c5380b9ea91ae6eca82 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 10:16:03 +1000 Subject: [PATCH 34/98] add an initial gossip validator Signed-off-by: Gabriel Fukushima --- .../ExecutionProofGossipValidator.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java new file mode 100644 index 00000000000..3073fa6b437 --- /dev/null +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -0,0 +1,59 @@ +package tech.pegasys.teku.statetransition.validation; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.collections.LimitedSet; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult; +import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb; + +import java.util.Map; +import java.util.Set; + +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + +public class ExecutionProofGossipValidator { + private static final Logger LOG = LogManager.getLogger(); + + private final Spec spec; + private final Set receivedValidExecutionProofSet; + private ZkChainConfiguration zkChainConfiguration; + + public static ExecutionProofGossipValidator create( + final Spec spec, final ZkChainConfiguration zkChainConfiguration) { + + return new ExecutionProofGossipValidator(spec, zkChainConfiguration, + LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue())); + } + + public ExecutionProofGossipValidator( + final Spec spec, final ZkChainConfiguration zkChainConfiguration, + final Set receivedValidExecutionProofSet) { + this.spec = spec; + this.zkChainConfiguration = zkChainConfiguration; + this.receivedValidExecutionProofSet = receivedValidExecutionProofSet; + } + + public SafeFuture validate(final ExecutionProof executionProof, final UInt64 subnetId) { + if(executionProof.getSubnetId().longValue() != subnetId.longValue()) { + LOG.warn("ExecutionProof subnetId does not match the gossip subnetId"); + return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); + } + + + if (receivedValidExecutionProofSet.contains(executionProof)) { + // Already seen and valid + return SafeFuture.completedFuture(InternalValidationResult.IGNORE); + } + + // Validated the execution proof + receivedValidExecutionProofSet.add(executionProof); + return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); + } +} From a2989d6c7653f5725a980b66dfeb50c28ea635c6 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 10:21:00 +1000 Subject: [PATCH 35/98] spotless Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/spec/config/Constants.java | 5 +- .../ExecutionProofsManager.java | 16 +++ .../ExecutionProofsManagerImpl.java | 16 +++ .../ExecutionProofGossipValidator.java | 86 ++++++++------ .../networking/eth2/ActiveEth2P2PNetwork.java | 13 ++- .../eth2/Eth2P2PNetworkBuilder.java | 6 +- .../gossip/ExecutionProofGossipChannel.java | 13 +-- .../eth2/gossip/forks/GossipForkManager.java | 10 +- .../gossip/forks/GossipForkSubscriptions.java | 6 +- .../ExecutionProofSubnetSubscriber.java | 108 ++++++++++-------- .../ExecutionProofSubnetTopicProvider.java | 39 ++++--- .../subnets/PeerSubnetSubscriptions.java | 65 ++++++----- .../eth2/gossip/subnets/SubnetScorer.java | 27 +++-- .../eth2/gossip/topics/GossipTopics.java | 3 +- .../discovery/discv5/NodeRecordConverter.java | 2 +- .../beaconchain/BeaconChainConfiguration.java | 4 +- .../beaconchain/BeaconChainController.java | 25 ++-- .../zkchain/ZkChainConfiguration.java | 7 +- 18 files changed, 264 insertions(+), 187 deletions(-) create mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java create mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java index 0971dd3af7b..e9e452417e1 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/Constants.java @@ -13,9 +13,8 @@ package tech.pegasys.teku.spec.config; -import tech.pegasys.teku.infrastructure.unsigned.UInt64; - import java.time.Duration; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; public class Constants { @@ -70,6 +69,6 @@ public class Constants { public static final Duration BUILDER_GET_PAYLOAD_TIMEOUT = Duration.ofSeconds(3); public static final int EPOCHS_PER_VALIDATOR_REGISTRATION_SUBMISSION = 1; - //ZkChain prototype + // ZkChain prototype public static final UInt64 MAX_EXECUTION_PROOF_SUBNETS = UInt64.valueOf(8); } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java new file mode 100644 index 00000000000..2dfdc088f1b --- /dev/null +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java @@ -0,0 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + +package tech.pegasys.teku.statetransition.executionproofs; + +public interface ExecutionProofsManager {} diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java new file mode 100644 index 00000000000..cb213587564 --- /dev/null +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java @@ -0,0 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + +package tech.pegasys.teku.statetransition.executionproofs; + +public class ExecutionProofsManagerImpl implements ExecutionProofsManager {} diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 3073fa6b437..68a1c38fec7 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -1,59 +1,69 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.statetransition.validation; +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + +import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tuweni.bytes.Bytes32; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.collections.LimitedSet; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; -import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult; -import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb; -import java.util.Map; -import java.util.Set; +public class ExecutionProofGossipValidator { + private static final Logger LOG = LogManager.getLogger(); -import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + private final Spec spec; + private final Set receivedValidExecutionProofSet; + private ZkChainConfiguration zkChainConfiguration; -public class ExecutionProofGossipValidator { - private static final Logger LOG = LogManager.getLogger(); + public static ExecutionProofGossipValidator create( + final Spec spec, final ZkChainConfiguration zkChainConfiguration) { - private final Spec spec; - private final Set receivedValidExecutionProofSet; - private ZkChainConfiguration zkChainConfiguration; + return new ExecutionProofGossipValidator( + spec, + zkChainConfiguration, + LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue())); + } - public static ExecutionProofGossipValidator create( - final Spec spec, final ZkChainConfiguration zkChainConfiguration) { + public ExecutionProofGossipValidator( + final Spec spec, + final ZkChainConfiguration zkChainConfiguration, + final Set receivedValidExecutionProofSet) { + this.spec = spec; + this.zkChainConfiguration = zkChainConfiguration; + this.receivedValidExecutionProofSet = receivedValidExecutionProofSet; + } - return new ExecutionProofGossipValidator(spec, zkChainConfiguration, - LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue())); + public SafeFuture validate( + final ExecutionProof executionProof, final UInt64 subnetId) { + if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { + LOG.warn("ExecutionProof subnetId does not match the gossip subnetId"); + return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); } - public ExecutionProofGossipValidator( - final Spec spec, final ZkChainConfiguration zkChainConfiguration, - final Set receivedValidExecutionProofSet) { - this.spec = spec; - this.zkChainConfiguration = zkChainConfiguration; - this.receivedValidExecutionProofSet = receivedValidExecutionProofSet; + if (receivedValidExecutionProofSet.contains(executionProof)) { + // Already seen and valid + return SafeFuture.completedFuture(InternalValidationResult.IGNORE); } - public SafeFuture validate(final ExecutionProof executionProof, final UInt64 subnetId) { - if(executionProof.getSubnetId().longValue() != subnetId.longValue()) { - LOG.warn("ExecutionProof subnetId does not match the gossip subnetId"); - return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); - } - - - if (receivedValidExecutionProofSet.contains(executionProof)) { - // Already seen and valid - return SafeFuture.completedFuture(InternalValidationResult.IGNORE); - } - - // Validated the execution proof - receivedValidExecutionProofSet.add(executionProof); - return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); - } + // Validated the execution proof + receivedValidExecutionProofSet.add(executionProof); + return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java index 5cfa5decb40..7fbcaa62107 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetwork.java @@ -148,7 +148,8 @@ private synchronized void startup() { eventChannels.subscribe( DataColumnSidecarGossipChannel.class, (sidecar, __) -> gossipForkManager.publishDataColumnSidecar(sidecar)); - eventChannels.subscribe(ExecutionProofGossipChannel.class, gossipForkManager::publishExecutionProof); + eventChannels.subscribe( + ExecutionProofGossipChannel.class, gossipForkManager::publishExecutionProof); if (recentChainData.isCloseToInSync()) { startGossip(); @@ -361,11 +362,11 @@ public void subscribeToDataColumnSidecarSubnetId(final int subnetId) { dataColumnSidecarSubnetService.addSubscription(subnetId); } - @Override - public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) { - gossipForkManager.unsubscribeFromDataColumnSidecarSubnetId(subnetId); - dataColumnSidecarSubnetService.removeSubscription(subnetId); - } + @Override + public void unsubscribeFromDataColumnSidecarSubnetId(final int subnetId) { + gossipForkManager.unsubscribeFromDataColumnSidecarSubnetId(subnetId); + dataColumnSidecarSubnetService.removeSubscription(subnetId); + } @Override public void subscribeToExecutionProofSubnetId(final int subnetId) { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 1486a463b01..ef956ecb045 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -216,7 +216,11 @@ public Eth2P2PNetwork build() { final GossipEncoding gossipEncoding = config.getGossipEncoding(); // Build core network and inject eth2 handlers final DiscoveryNetwork network = - buildNetwork(gossipEncoding, syncCommitteeSubnetService, dataColumnSidecarSubnetService, executionProofSubnetService); + buildNetwork( + gossipEncoding, + syncCommitteeSubnetService, + dataColumnSidecarSubnetService, + executionProofSubnetService); final GossipForkManager gossipForkManager = buildGossipForkManager(gossipEncoding, network); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java index e460a759697..8803a699f34 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -13,23 +13,18 @@ package tech.pegasys.teku.networking.eth2.gossip; +import java.util.List; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.events.ChannelInterface; -import tech.pegasys.teku.infrastructure.events.VoidReturningChannelInterface; -import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; -import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; - -import java.util.List; public interface ExecutionProofGossipChannel extends ChannelInterface { ExecutionProofGossipChannel NOOP = executionProof -> SafeFuture.COMPLETE; - default SafeFuture publishExecutionProof( - final List executionProofs) { - return SafeFuture.allOf(executionProofs.stream().map(this::publishExecutionProof)); + default SafeFuture publishExecutionProof(final List executionProofs) { + return SafeFuture.allOf(executionProofs.stream().map(this::publishExecutionProof)); } - SafeFuture publishExecutionProof(ExecutionProof executionProof); + SafeFuture publishExecutionProof(ExecutionProof executionProof); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 4028b0fdf3f..71106ab231f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -190,15 +190,15 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo GossipForkSubscriptions::publishDataColumnSidecar); } - public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { - //for now we don't have a slot in the message data (execution proof) to use - // I believe it's safe to just check the current epoch - return publishMessageWithFeedback( + public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { + // for now we don't have a slot in the message data (execution proof) to use + // I believe it's safe to just check the current epoch + return publishMessageWithFeedback( spec.computeStartSlotAtEpoch(currentEpoch.orElseThrow()), executionProof, "execution proof", GossipForkSubscriptions::publishExecutionProof); - } + } public void publishSyncCommitteeMessage(final ValidatableSyncCommitteeMessage message) { publishMessage( diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index e560afd57a5..e9764ce4af8 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -46,9 +46,9 @@ default SafeFuture publishBlobSidecar(final BlobSidecar blobSidecar) { return SafeFuture.COMPLETE; } - default SafeFuture publishExecutionProof(final ExecutionProof executionProof) { - return SafeFuture.COMPLETE; - } + default SafeFuture publishExecutionProof(final ExecutionProof executionProof) { + return SafeFuture.COMPLETE; + } void subscribeToAttestationSubnetId(int subnetId); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java index 8d7513d92a6..b751d2a0373 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java @@ -1,7 +1,25 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.networking.eth2.gossip.subnets; +import static java.util.stream.Collectors.toList; +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; +import java.util.Collection; +import java.util.stream.IntStream; import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.ethereum.events.SlotEventsChannel; import tech.pegasys.teku.infrastructure.unsigned.UInt64; @@ -9,64 +27,56 @@ import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.Spec; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.IntStream; - -import static java.util.stream.Collectors.toList; -import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; - public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { - private final Eth2P2PNetwork eth2P2PNetwork; - private final ZkChainConfiguration zkChainConfiguration; - private final UInt256 nodeId; - private final Spec spec; + private final Eth2P2PNetwork eth2P2PNetwork; + private final ZkChainConfiguration zkChainConfiguration; + private final UInt256 nodeId; + private final Spec spec; - private IntSet currentSubscribedSubnets = IntSet.of(); - private UInt64 lastEpoch = UInt64.MAX_VALUE; + private IntSet currentSubscribedSubnets = IntSet.of(); + private UInt64 lastEpoch = UInt64.MAX_VALUE; + public ExecutionProofSubnetSubscriber( + final Spec spec, + final Eth2P2PNetwork eth2P2PNetwork, + final UInt256 nodeId, + final ZkChainConfiguration zkChainConfiguration) { + this.spec = spec; + this.eth2P2PNetwork = eth2P2PNetwork; + this.nodeId = nodeId; + this.zkChainConfiguration = zkChainConfiguration; + } - public ExecutionProofSubnetSubscriber( - final Spec spec, - final Eth2P2PNetwork eth2P2PNetwork, - final UInt256 nodeId, - final ZkChainConfiguration zkChainConfiguration) { - this.spec = spec; - this.eth2P2PNetwork = eth2P2PNetwork; - this.nodeId = nodeId; - this.zkChainConfiguration = zkChainConfiguration; - } - - private void subscribeToSubnets(final Collection newSubscriptions) { + private void subscribeToSubnets(final Collection newSubscriptions) { - IntOpenHashSet newSubscriptionsSet = new IntOpenHashSet(newSubscriptions); + IntOpenHashSet newSubscriptionsSet = new IntOpenHashSet(newSubscriptions); - for (int oldSubnet : currentSubscribedSubnets) { - if (!newSubscriptionsSet.contains(oldSubnet)) { - eth2P2PNetwork.unsubscribeFromExecutionProofSubnetId(oldSubnet); - } - } - - for (int newSubnet : newSubscriptionsSet) { - if (!currentSubscribedSubnets.contains(newSubnet)) { - eth2P2PNetwork.subscribeToExecutionProofSubnetId(newSubnet); - } - } - - currentSubscribedSubnets = newSubscriptionsSet; + for (int oldSubnet : currentSubscribedSubnets) { + if (!newSubscriptionsSet.contains(oldSubnet)) { + eth2P2PNetwork.unsubscribeFromExecutionProofSubnetId(oldSubnet); + } } - private void onEpoch(final UInt64 epoch) { - subscribeToSubnets(IntStream.range(0,MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); + for (int newSubnet : newSubscriptionsSet) { + if (!currentSubscribedSubnets.contains(newSubnet)) { + eth2P2PNetwork.subscribeToExecutionProofSubnetId(newSubnet); + } } - @Override - public synchronized void onSlot(final UInt64 slot) { - UInt64 epoch = spec.computeEpochAtSlot(slot); - if (!epoch.equals(lastEpoch)) { - lastEpoch = epoch; - onEpoch(epoch); - } + currentSubscribedSubnets = newSubscriptionsSet; + } + + private void onEpoch(final UInt64 epoch) { + subscribeToSubnets( + IntStream.range(0, MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); + } + + @Override + public synchronized void onSlot(final UInt64 slot) { + UInt64 epoch = spec.computeEpochAtSlot(slot); + if (!epoch.equals(lastEpoch)) { + lastEpoch = epoch; + onEpoch(epoch); } + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java index 19b4bc5609c..1cebd65dace 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java @@ -1,23 +1,36 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.networking.eth2.gossip.subnets; +import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopics.getExecutionProofSubnetTopic; + import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; import tech.pegasys.teku.storage.client.RecentChainData; -import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopics.getExecutionProofSubnetTopic; - public class ExecutionProofSubnetTopicProvider { - private final RecentChainData recentChainData; - private final GossipEncoding gossipEncoding; + private final RecentChainData recentChainData; + private final GossipEncoding gossipEncoding; - public ExecutionProofSubnetTopicProvider( - final RecentChainData recentChainData, final GossipEncoding gossipEncoding) { - this.recentChainData = recentChainData; - this.gossipEncoding = gossipEncoding; - } + public ExecutionProofSubnetTopicProvider( + final RecentChainData recentChainData, final GossipEncoding gossipEncoding) { + this.recentChainData = recentChainData; + this.gossipEncoding = gossipEncoding; + } - public String getTopicForSubnet(final int subnetId) { - final Bytes4 forkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); - return getExecutionProofSubnetTopic(forkDigest, subnetId, gossipEncoding); - } + public String getTopicForSubnet(final int subnetId) { + final Bytes4 forkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); + return getExecutionProofSubnetTopic(forkDigest, subnetId, gossipEncoding); + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index dde94f0f775..c5723c8b634 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -13,6 +13,8 @@ package tech.pegasys.teku.networking.eth2.gossip.subnets; +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + import com.google.common.annotations.VisibleForTesting; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; @@ -40,8 +42,6 @@ import tech.pegasys.teku.spec.config.SpecConfigFulu; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsSupplier; -import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; - public class PeerSubnetSubscriptions { private final SubnetSubscriptions attestationSubnetSubscriptions; @@ -92,7 +92,10 @@ public static PeerSubnetSubscriptions create( .orElse(1); final PeerSubnetSubscriptions subscriptions = - builder(currentSchemaDefinitions, SszBitvectorSchema.create(dataColumnSidecarSubnetCount), SszBitvectorSchema.create(MAX_EXECUTION_PROOF_SUBNETS.intValue())) + builder( + currentSchemaDefinitions, + SszBitvectorSchema.create(dataColumnSidecarSubnetCount), + SszBitvectorSchema.create(MAX_EXECUTION_PROOF_SUBNETS.intValue())) .targetSubnetSubscriberCount(targetSubnetSubscriberCount) .nodeIdToDataColumnSidecarSubnetsCalculator(nodeIdToDataColumnSidecarSubnetsCalculator) .attestationSubnetSubscriptions( @@ -140,22 +143,22 @@ public static PeerSubnetSubscriptions create( Collections.emptySet()) .forEach(subscriber -> b.addSubscriber(columnSubnet, subscriber)); })) - .executionProofSubnetSubscriptions( - b -> - executionProofSubnetService - .getSubnets() - .forEach( - execSubnet -> { - b.addRelevantSubnet(execSubnet); - // Execution payloads are gossiped on the same topic as - // data column sidecars - subscribersByTopic - .getOrDefault( - exeecutionProofSubnetTopicProvider.getTopicForSubnet( - execSubnet), - Collections.emptySet()) - .forEach(subscriber -> b.addSubscriber(execSubnet, subscriber)); - })) + .executionProofSubnetSubscriptions( + b -> + executionProofSubnetService + .getSubnets() + .forEach( + execSubnet -> { + b.addRelevantSubnet(execSubnet); + // Execution payloads are gossiped on the same topic as + // data column sidecars + subscribersByTopic + .getOrDefault( + exeecutionProofSubnetTopicProvider.getTopicForSubnet( + execSubnet), + Collections.emptySet()) + .forEach(subscriber -> b.addSubscriber(execSubnet, subscriber)); + })) .build(); updateMetrics(currentSchemaDefinitions, subnetPeerCountGauge, subscriptions); return subscriptions; @@ -195,7 +198,10 @@ static Builder builder( final SchemaDefinitionsSupplier currentSchemaDefinitions, final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, final SszBitvectorSchema executionProofSubnetSubscription) { - return new Builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema, executionProofSubnetSubscription); + return new Builder( + currentSchemaDefinitions, + dataColumnSidecarSubnetBitmaskSchema, + executionProofSubnetSubscription); } @VisibleForTesting @@ -203,7 +209,10 @@ static PeerSubnetSubscriptions createEmpty( final SchemaDefinitionsSupplier currentSchemaDefinitions, final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, final SszBitvectorSchema executionProofSubnetSubscription) { - return builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema, executionProofSubnetSubscription) + return builder( + currentSchemaDefinitions, + dataColumnSidecarSubnetBitmaskSchema, + executionProofSubnetSubscription) .nodeIdToDataColumnSidecarSubnetsCalculator(NodeIdToDataColumnSidecarSubnetsCalculator.NOOP) .build(); } @@ -220,9 +229,9 @@ public int getSubscriberCountForDataColumnSidecarSubnet(final int subnetId) { return dataColumnSidecarSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); } - public int getSubscriberCountForExecutionProofSubnet(final int subnetId) { - return executionProofSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); - } + public int getSubscriberCountForExecutionProofSubnet(final int subnetId) { + return executionProofSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); + } public SszBitvector getAttestationSubnetSubscriptions(final NodeId peerId) { return attestationSubnetSubscriptions.getSubnetSubscriptions(peerId); @@ -260,7 +269,7 @@ public boolean isDataColumnSidecarSubnetRelevant(final int subnetId) { } public boolean isExecutionProofSubnetRelevant(final int subnetId) { - return executionProofSubnetSubscriptions.isSubnetRelevant(subnetId); + return executionProofSubnetSubscriptions.isSubnetRelevant(subnetId); } public PeerScorer createScorer() { @@ -403,8 +412,8 @@ private Builder( SubnetSubscriptions.builder(currentSchemaDefinitions.getSyncnetsENRFieldSchema()); dataColumnSidecarSubnetSubscriptions = SubnetSubscriptions.builder(dataColumnSidecarSubnetBitmaskSchema); - executionProofSubnetSubscriptions = - SubnetSubscriptions.builder(executionProofSubnetSubscription); + executionProofSubnetSubscriptions = + SubnetSubscriptions.builder(executionProofSubnetSubscription); } public PeerSubnetSubscriptions build() { @@ -412,7 +421,7 @@ public PeerSubnetSubscriptions build() { attestationSubnetSubscriptions.build(), syncCommitteeSubnetSubscriptions.build(), dataColumnSidecarSubnetSubscriptions.build(), - executionProofSubnetSubscriptions.build(), + executionProofSubnetSubscriptions.build(), nodeIdToDataColumnSidecarSubnetsCalculator, targetSubnetSubscriberCount); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java index 7d2dc911bdb..e644643b0a7 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java @@ -59,7 +59,7 @@ public int scoreCandidatePeer(final DiscoveryPeer candidate) { candidate.getSyncCommitteeSubnets(), peerSubnetSubscriptions.getDataColumnSidecarSubnetSubscriptionsByNodeId( UInt256.fromBytes(candidate.getNodeId()), candidate.getDasCustodySubnetCount()), - candidate.getExecutionProofSubnets()); + candidate.getExecutionProofSubnets()); } // @Override @@ -119,20 +119,27 @@ private int score( }) .sum(); - final int executionProofSubnetScore = - executionProofSubnetSubscriptions.map(executionProof -> - executionProof - .streamAllSetBits() - .filter(peerSubnetSubscriptions::isExecutionProofSubnetRelevant) - .map( + final int executionProofSubnetScore = + executionProofSubnetSubscriptions + .map( + executionProof -> + executionProof + .streamAllSetBits() + .filter(peerSubnetSubscriptions::isExecutionProofSubnetRelevant) + .map( subnetId -> { int subscriberCount = - peerSubnetSubscriptions.getSubscriberCountForExecutionProofSubnet(subnetId); + peerSubnetSubscriptions.getSubscriberCountForExecutionProofSubnet( + subnetId); return subscriberCountToScore.applyAsInt(subscriberCount); }) - .sum()).orElse(0); + .sum()) + .orElse(0); - return attestationSubnetScore + syncCommitteeSubnetScore + dataColumnSidecarSubnetScore + executionProofSubnetScore; + return attestationSubnetScore + + syncCommitteeSubnetScore + + dataColumnSidecarSubnetScore + + executionProofSubnetScore; } private int scoreSubnetForExistingPeer(final int subscriberCount) { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java index 1b25e50805e..46cf24ffb92 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java @@ -72,7 +72,8 @@ public static String getDataColumnSidecarSubnetTopic( return getTopic( forkDigest, GossipTopicName.getDataColumnSidecarSubnetTopicName(subnetId), gossipEncoding); } - public static String getExecutionProofSubnetTopic( + + public static String getExecutionProofSubnetTopic( final Bytes4 forkDigest, final int subnetId, final GossipEncoding gossipEncoding) { return getTopic( forkDigest, GossipTopicName.getExecutionProofSubnetTopicName(subnetId), gossipEncoding); diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java index 15778ee585b..1b5266b51d6 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java @@ -90,7 +90,7 @@ private static DiscoveryPeer socketAddressToDiscoveryPeer( NEXT_FORK_DIGEST_ENR_FIELD, SszPrimitiveSchemas.BYTES4_SCHEMA::sszDeserialize) .map(SszBytes4::get); - //TODO - see how we gonna define this, if we want to use it + // TODO - see how we gonna define this, if we want to use it final Optional executionProofSubnets = Optional.empty(); return new DiscoveryPeer( diff --git a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java index 7b5b5cf5d77..28bf4cc6100 100644 --- a/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java +++ b/services/beaconchain/src/main/java/tech/pegasys/teku/services/beaconchain/BeaconChainConfiguration.java @@ -119,5 +119,7 @@ public BeaconChainControllerFactory getBeaconChainControllerFactory() { return beaconChainControllerFactory; } - public ZkChainConfiguration zkChainConfiguration() { return zkChainConfiguration; } + public ZkChainConfiguration zkChainConfiguration() { + return zkChainConfiguration; + } } 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 7aa43637b08..0c7e6507b43 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 @@ -87,7 +87,6 @@ import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.BlockGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.DataColumnSidecarGossipChannel; -import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSubnetsSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSyncCommitteeSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber; @@ -668,24 +667,18 @@ protected void initExecutionLayer() { executionLayer = eventChannels.getPublisher(ExecutionLayerChannel.class, beaconAsyncRunner); } - protected void initKzChain(){ - ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); + protected void initKzChain() { + ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); - if(zkConfig.isStatelessValidationEnabled()){ - final ExecutionProofGossipValidator executionProofGossipValidator = - ExecutionProofGossipValidator.create(spec, zkConfig); + if (zkConfig.isStatelessValidationEnabled()) { + final ExecutionProofGossipValidator executionProofGossipValidator = + ExecutionProofGossipValidator.create(spec, zkConfig); - ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = - new ExecutionProofSubnetSubscriber( - spec, - p2pNetwork, - nodeId, - zkConfig); + ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = + new ExecutionProofSubnetSubscriber(spec, p2pNetwork, nodeId, zkConfig); - - - eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); - } + eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); + } } protected void initKzg() { 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 a255334b147..55773ea988c 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 @@ -75,9 +75,10 @@ public Builder statelessMinProofsRequired(final int statelessMinProofsRequired) } public ZkChainConfiguration build() { - if(generateExecutionProofsEnabled && !statelessValidationEnabled) { - throw new IllegalStateException("Can't generate execution proofs when statelessValidationEnabled is false"); - } + if (generateExecutionProofsEnabled && !statelessValidationEnabled) { + throw new IllegalStateException( + "Can't generate execution proofs when statelessValidationEnabled is false"); + } return new ZkChainConfiguration( statelessValidationEnabled, generateExecutionProofsEnabled, statelessMinProofsRequired); } From 06e2fdfffbd9651bf47b8d09fc9b8de24b331ab0 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 12:49:51 +1000 Subject: [PATCH 36/98] fix assemble Signed-off-by: Gabriel Fukushima --- ethereum/statetransition/build.gradle | 1 + .../ExecutionProofGossipValidator.java | 12 +++++------- networking/eth2/build.gradle | 1 + .../networking/eth2/Eth2P2PNetworkBuilder.java | 5 +++++ .../subnets/ExecutionProofSubnetSubscriber.java | 16 +++------------- .../gossip/subnets/PeerSubnetSubscriptions.java | 4 ++-- .../eth2/gossip/topics/GossipTopicName.java | 3 +++ .../networking/eth2/Eth2P2PNetworkFactory.java | 9 +++++++++ services/beaconchain/build.gradle | 1 + .../beaconchain/BeaconChainController.java | 7 ++++--- 10 files changed, 34 insertions(+), 25 deletions(-) diff --git a/ethereum/statetransition/build.gradle b/ethereum/statetransition/build.gradle index da1fe9c7336..74a9f73b215 100644 --- a/ethereum/statetransition/build.gradle +++ b/ethereum/statetransition/build.gradle @@ -22,6 +22,7 @@ dependencies { implementation project(':infrastructure:subscribers') implementation project(':infrastructure:time') implementation project(':infrastructure:serviceutils') + implementation project(':services:zkchain') implementation project(':storage') implementation project(':storage:api') diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 68a1c38fec7..f3ee698248b 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -28,24 +28,22 @@ public class ExecutionProofGossipValidator { private static final Logger LOG = LogManager.getLogger(); - private final Spec spec; + private final Set receivedValidExecutionProofSet; - private ZkChainConfiguration zkChainConfiguration; + @SuppressWarnings("unused") + private final ZkChainConfiguration zkChainConfiguration; - public static ExecutionProofGossipValidator create( - final Spec spec, final ZkChainConfiguration zkChainConfiguration) { + public static ExecutionProofGossipValidator create( final ZkChainConfiguration zkChainConfiguration) { return new ExecutionProofGossipValidator( - spec, zkChainConfiguration, LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue())); } public ExecutionProofGossipValidator( - final Spec spec, final ZkChainConfiguration zkChainConfiguration, final Set receivedValidExecutionProofSet) { - this.spec = spec; + this.zkChainConfiguration = zkChainConfiguration; this.receivedValidExecutionProofSet = receivedValidExecutionProofSet; } diff --git a/networking/eth2/build.gradle b/networking/eth2/build.gradle index 13f9dad2d2f..7004af275b4 100644 --- a/networking/eth2/build.gradle +++ b/networking/eth2/build.gradle @@ -15,6 +15,7 @@ dependencies { implementation project(':infrastructure:ssz') implementation project(':storage') implementation project(':storage:api') + implementation project(':services:zkchain') implementation project(':infrastructure:serviceutils') implementation 'io.libp2p:jvm-libp2p' diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index ef956ecb045..42523270c21 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -49,6 +49,7 @@ import tech.pegasys.teku.networking.eth2.gossip.forks.versions.GossipForkSubscriptionsPhase0; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetTopicProvider; +import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.NodeIdToDataColumnSidecarSubnetsCalculator; import tech.pegasys.teku.networking.eth2.gossip.subnets.PeerSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubnetTopicProvider; @@ -535,6 +536,9 @@ protected DiscoveryNetwork buildNetwork( final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider = new DataColumnSidecarSubnetTopicProvider( combinedChainDataClient.getRecentChainData(), gossipEncoding); + final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider = + new ExecutionProofSubnetTopicProvider( + combinedChainDataClient.getRecentChainData(), gossipEncoding); final TargetPeerRange targetPeerRange = new TargetPeerRange( @@ -574,6 +578,7 @@ protected DiscoveryNetwork buildNetwork( syncCommitteeSubnetService, dataColumnSidecarSubnetTopicProvider, dataColumnSidecarSubnetService, + executionProofSubnetTopicProvider, executionProofSubnetService, config.getTargetSubnetSubscriberCount(), subnetPeerCountGauge), diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java index b751d2a0373..25e8f11f48f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java @@ -29,8 +29,6 @@ public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { private final Eth2P2PNetwork eth2P2PNetwork; - private final ZkChainConfiguration zkChainConfiguration; - private final UInt256 nodeId; private final Spec spec; private IntSet currentSubscribedSubnets = IntSet.of(); @@ -38,13 +36,9 @@ public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { public ExecutionProofSubnetSubscriber( final Spec spec, - final Eth2P2PNetwork eth2P2PNetwork, - final UInt256 nodeId, - final ZkChainConfiguration zkChainConfiguration) { + final Eth2P2PNetwork eth2P2PNetwork) { this.spec = spec; this.eth2P2PNetwork = eth2P2PNetwork; - this.nodeId = nodeId; - this.zkChainConfiguration = zkChainConfiguration; } private void subscribeToSubnets(final Collection newSubscriptions) { @@ -66,17 +60,13 @@ private void subscribeToSubnets(final Collection newSubscriptions) { currentSubscribedSubnets = newSubscriptionsSet; } - private void onEpoch(final UInt64 epoch) { - subscribeToSubnets( - IntStream.range(0, MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); - } - @Override public synchronized void onSlot(final UInt64 slot) { UInt64 epoch = spec.computeEpochAtSlot(slot); if (!epoch.equals(lastEpoch)) { lastEpoch = epoch; - onEpoch(epoch); + subscribeToSubnets( + IntStream.range(0, MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); } } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index c5723c8b634..d026ee2cf6d 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -76,7 +76,7 @@ public static PeerSubnetSubscriptions create( final SubnetSubscriptionService syncCommitteeSubnetService, final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider, final SubnetSubscriptionService dataColumnSidecarSubnetService, - final ExecutionProofSubnetTopicProvider exeecutionProofSubnetTopicProvider, + final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider, final SubnetSubscriptionService executionProofSubnetService, final int targetSubnetSubscriberCount, final SettableLabelledGauge subnetPeerCountGauge) { @@ -154,7 +154,7 @@ public static PeerSubnetSubscriptions create( // data column sidecars subscribersByTopic .getOrDefault( - exeecutionProofSubnetTopicProvider.getTopicForSubnet( + executionProofSubnetTopicProvider.getTopicForSubnet( execSubnet), Collections.emptySet()) .forEach(subscriber -> b.addSubscriber(execSubnet, subscriber)); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java index fc779f24eb6..b0783f3c4f7 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java @@ -44,4 +44,7 @@ public static String getBlobSidecarSubnetTopicName(final int subnetId) { public static String getDataColumnSidecarSubnetTopicName(final int subnetId) { return "data_column_sidecar_" + subnetId; } + public static String getExecutionProofSubnetTopicName(final int subnetId) { + return "execution_proof_" + subnetId; + } } diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 8fae2f97666..9d389e60fa1 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -63,6 +63,7 @@ import tech.pegasys.teku.networking.eth2.gossip.forks.versions.GossipForkSubscriptionsPhase0; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetTopicProvider; +import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.NodeIdToDataColumnSidecarSubnetsCalculator; import tech.pegasys.teku.networking.eth2.gossip.subnets.PeerSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubnetTopicProvider; @@ -221,6 +222,8 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { new SubnetSubscriptionService(); final SubnetSubscriptionService dataColumnSidecarSubnetService = new SubnetSubscriptionService(); + final SubnetSubscriptionService executionProofSubnetService = + new SubnetSubscriptionService(); final EarliestAvailableBlockSlot earliestAvailableBlockSlot = new EarliestAvailableBlockSlot( historicalChainData, timeProvider, earliestAvailableBlockSlotFrequency); @@ -230,6 +233,9 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider = new DataColumnSidecarSubnetTopicProvider( combinedChainDataClient.getRecentChainData(), gossipEncoding); + final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider = + new ExecutionProofSubnetTopicProvider( + combinedChainDataClient.getRecentChainData(), gossipEncoding); if (rpcEncoding == null) { rpcEncoding = @@ -349,6 +355,8 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { syncCommitteeSubnetService, dataColumnSidecarSubnetTopicProvider, dataColumnSidecarSubnetService, + executionProofSubnetTopicProvider, + executionProofSubnetService, config.getTargetSubnetSubscriberCount(), subnetPeerCountGauge), reputationManager, @@ -382,6 +390,7 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { attestationSubnetService, syncCommitteeSubnetService, dataColumnSidecarSubnetService, + executionProofSubnetService, gossipEncoding, GossipConfigurator.NOOP, processedAttestationSubscriptionProvider, diff --git a/services/beaconchain/build.gradle b/services/beaconchain/build.gradle index fc903a0a4ff..f955d57d040 100644 --- a/services/beaconchain/build.gradle +++ b/services/beaconchain/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation project(':services:powchain') implementation project(':services:timer') implementation project(':services:executionlayer') + implementation project(':services:zkchain') implementation project(':infrastructure:ssz') implementation project(':storage') implementation project(':storage:api') 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 0c7e6507b43..ae85ccfaf98 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 @@ -671,11 +671,12 @@ protected void initKzChain() { ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { - final ExecutionProofGossipValidator executionProofGossipValidator = - ExecutionProofGossipValidator.create(spec, zkConfig); +// final ExecutionProofGossipValidator executionProofGossipValidator = +// ExecutionProofGossipValidator.create(zkConfig); ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = - new ExecutionProofSubnetSubscriber(spec, p2pNetwork, nodeId, zkConfig); + new ExecutionProofSubnetSubscriber(spec, p2pNetwork); + new ExecutionProofSubnetSubscriber(spec, p2pNetwork); eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); } From 934de8cd2a3d2a3d664f3179caa91581a7c6ce0e Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 12:50:21 +1000 Subject: [PATCH 37/98] spotless Signed-off-by: Gabriel Fukushima --- .../validation/ExecutionProofGossipValidator.java | 6 +++--- .../gossip/subnets/ExecutionProofSubnetSubscriber.java | 10 +++------- .../eth2/gossip/subnets/PeerSubnetSubscriptions.java | 2 +- .../networking/eth2/gossip/topics/GossipTopicName.java | 1 + .../teku/networking/eth2/Eth2P2PNetworkFactory.java | 10 +++++----- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index f3ee698248b..89da8b2650c 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -22,18 +22,18 @@ import tech.pegasys.teku.infrastructure.collections.LimitedSet; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; -import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; public class ExecutionProofGossipValidator { private static final Logger LOG = LogManager.getLogger(); - private final Set receivedValidExecutionProofSet; + @SuppressWarnings("unused") private final ZkChainConfiguration zkChainConfiguration; - public static ExecutionProofGossipValidator create( final ZkChainConfiguration zkChainConfiguration) { + public static ExecutionProofGossipValidator create( + final ZkChainConfiguration zkChainConfiguration) { return new ExecutionProofGossipValidator( zkChainConfiguration, diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java index 25e8f11f48f..43079609b33 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java @@ -20,11 +20,9 @@ import it.unimi.dsi.fastutil.ints.IntSet; import java.util.Collection; import java.util.stream.IntStream; -import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.ethereum.events.SlotEventsChannel; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.networking.eth2.Eth2P2PNetwork; -import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.Spec; public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { @@ -34,9 +32,7 @@ public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { private IntSet currentSubscribedSubnets = IntSet.of(); private UInt64 lastEpoch = UInt64.MAX_VALUE; - public ExecutionProofSubnetSubscriber( - final Spec spec, - final Eth2P2PNetwork eth2P2PNetwork) { + public ExecutionProofSubnetSubscriber(final Spec spec, final Eth2P2PNetwork eth2P2PNetwork) { this.spec = spec; this.eth2P2PNetwork = eth2P2PNetwork; } @@ -65,8 +61,8 @@ public synchronized void onSlot(final UInt64 slot) { UInt64 epoch = spec.computeEpochAtSlot(slot); if (!epoch.equals(lastEpoch)) { lastEpoch = epoch; - subscribeToSubnets( - IntStream.range(0, MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); + subscribeToSubnets( + IntStream.range(0, MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); } } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index d026ee2cf6d..0d5c038c9ba 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -154,7 +154,7 @@ public static PeerSubnetSubscriptions create( // data column sidecars subscribersByTopic .getOrDefault( - executionProofSubnetTopicProvider.getTopicForSubnet( + executionProofSubnetTopicProvider.getTopicForSubnet( execSubnet), Collections.emptySet()) .forEach(subscriber -> b.addSubscriber(execSubnet, subscriber)); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java index b0783f3c4f7..305f348c326 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicName.java @@ -44,6 +44,7 @@ public static String getBlobSidecarSubnetTopicName(final int subnetId) { public static String getDataColumnSidecarSubnetTopicName(final int subnetId) { return "data_column_sidecar_" + subnetId; } + public static String getExecutionProofSubnetTopicName(final int subnetId) { return "execution_proof_" + subnetId; } diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 9d389e60fa1..6502bb60848 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -222,8 +222,8 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { new SubnetSubscriptionService(); final SubnetSubscriptionService dataColumnSidecarSubnetService = new SubnetSubscriptionService(); - final SubnetSubscriptionService executionProofSubnetService = - new SubnetSubscriptionService(); + final SubnetSubscriptionService executionProofSubnetService = + new SubnetSubscriptionService(); final EarliestAvailableBlockSlot earliestAvailableBlockSlot = new EarliestAvailableBlockSlot( historicalChainData, timeProvider, earliestAvailableBlockSlotFrequency); @@ -355,8 +355,8 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { syncCommitteeSubnetService, dataColumnSidecarSubnetTopicProvider, dataColumnSidecarSubnetService, - executionProofSubnetTopicProvider, - executionProofSubnetService, + executionProofSubnetTopicProvider, + executionProofSubnetService, config.getTargetSubnetSubscriberCount(), subnetPeerCountGauge), reputationManager, @@ -390,7 +390,7 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { attestationSubnetService, syncCommitteeSubnetService, dataColumnSidecarSubnetService, - executionProofSubnetService, + executionProofSubnetService, gossipEncoding, GossipConfigurator.NOOP, processedAttestationSubscriptionProvider, From 43208618a8ac0bde922caff02586fa112fc0eca3 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 12:50:28 +1000 Subject: [PATCH 38/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/services/beaconchain/BeaconChainController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 ae85ccfaf98..0a41f27ba98 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 @@ -224,7 +224,6 @@ import tech.pegasys.teku.statetransition.validation.BlockGossipValidator; import tech.pegasys.teku.statetransition.validation.BlockValidator; import tech.pegasys.teku.statetransition.validation.DataColumnSidecarGossipValidator; -import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; import tech.pegasys.teku.statetransition.validation.GossipValidationHelper; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; import tech.pegasys.teku.statetransition.validation.ProposerSlashingValidator; @@ -671,12 +670,12 @@ protected void initKzChain() { ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { -// final ExecutionProofGossipValidator executionProofGossipValidator = -// ExecutionProofGossipValidator.create(zkConfig); + // final ExecutionProofGossipValidator executionProofGossipValidator = + // ExecutionProofGossipValidator.create(zkConfig); ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = new ExecutionProofSubnetSubscriber(spec, p2pNetwork); - new ExecutionProofSubnetSubscriber(spec, p2pNetwork); + new ExecutionProofSubnetSubscriber(spec, p2pNetwork); eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); } From 058ce7e4f15e8778e4adf9ea2b4494babcba9e67 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 14:06:58 +1000 Subject: [PATCH 39/98] spotless and fix assemble Signed-off-by: Gabriel Fukushima --- ethereum/statetransition/build.gradle | 1 - .../validation/ExecutionProofGossipValidator.java | 14 ++------------ services/beaconchain/build.gradle | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/ethereum/statetransition/build.gradle b/ethereum/statetransition/build.gradle index 74a9f73b215..da1fe9c7336 100644 --- a/ethereum/statetransition/build.gradle +++ b/ethereum/statetransition/build.gradle @@ -22,7 +22,6 @@ dependencies { implementation project(':infrastructure:subscribers') implementation project(':infrastructure:time') implementation project(':infrastructure:serviceutils') - implementation project(':services:zkchain') implementation project(':storage') implementation project(':storage:api') diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 89da8b2650c..6a1fab38973 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -21,7 +21,6 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.collections.LimitedSet; import tech.pegasys.teku.infrastructure.unsigned.UInt64; -import tech.pegasys.teku.services.zkchain.ZkChainConfiguration; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; public class ExecutionProofGossipValidator { @@ -29,22 +28,13 @@ public class ExecutionProofGossipValidator { private final Set receivedValidExecutionProofSet; - @SuppressWarnings("unused") - private final ZkChainConfiguration zkChainConfiguration; - - public static ExecutionProofGossipValidator create( - final ZkChainConfiguration zkChainConfiguration) { - + public static ExecutionProofGossipValidator create() { return new ExecutionProofGossipValidator( - zkChainConfiguration, LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue())); } - public ExecutionProofGossipValidator( - final ZkChainConfiguration zkChainConfiguration, - final Set receivedValidExecutionProofSet) { + public ExecutionProofGossipValidator(final Set receivedValidExecutionProofSet) { - this.zkChainConfiguration = zkChainConfiguration; this.receivedValidExecutionProofSet = receivedValidExecutionProofSet; } diff --git a/services/beaconchain/build.gradle b/services/beaconchain/build.gradle index f955d57d040..c7a112330ca 100644 --- a/services/beaconchain/build.gradle +++ b/services/beaconchain/build.gradle @@ -27,7 +27,7 @@ dependencies { implementation project(':services:powchain') implementation project(':services:timer') implementation project(':services:executionlayer') - implementation project(':services:zkchain') + implementation project(':services:zkchain') implementation project(':infrastructure:ssz') implementation project(':storage') implementation project(':storage:api') From d260a0d11c2b0411b3ce98d90c5db756974f2ee2 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 14:32:04 +1000 Subject: [PATCH 40/98] remove the bit vector from discovery peer for now Signed-off-by: Gabriel Fukushima --- .../teku/networking/p2p/discovery/DiscoveryPeer.java | 9 +-------- .../networking/p2p/discovery/discv5/DiscV5Service.java | 1 - .../p2p/discovery/discv5/NodeRecordConverter.java | 3 +-- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java index 06731b2daac..8bf0ad64695 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/DiscoveryPeer.java @@ -29,7 +29,6 @@ public class DiscoveryPeer { private final Optional enrForkId; private final SszBitvector persistentAttestationSubnets; private final SszBitvector syncCommitteeSubnets; - private final Optional executionProofSubnets; private final Optional dasCustodySubnetCount; private final Optional nextForkDigest; @@ -41,8 +40,7 @@ public DiscoveryPeer( final SszBitvector persistentAttestationSubnets, final SszBitvector syncCommitteeSubnets, final Optional dasCustodySubnetCount, - final Optional nextForkDigest, - final Optional executionProofSubnets) { + final Optional nextForkDigest) { this.publicKey = publicKey; this.nodeId = nodeId; this.nodeAddress = nodeAddress; @@ -51,7 +49,6 @@ public DiscoveryPeer( this.syncCommitteeSubnets = syncCommitteeSubnets; this.dasCustodySubnetCount = dasCustodySubnetCount; this.nextForkDigest = nextForkDigest; - this.executionProofSubnets = executionProofSubnets; } public Bytes getPublicKey() { @@ -78,10 +75,6 @@ public SszBitvector getSyncCommitteeSubnets() { return syncCommitteeSubnets; } - public Optional getExecutionProofSubnets() { - return executionProofSubnets; - } - public Optional getDasCustodySubnetCount() { return dasCustodySubnetCount; } diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java index eb738ab57a4..a4bd609cc2c 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/DiscV5Service.java @@ -292,7 +292,6 @@ public Optional> getDiscoveryAddresses() { currentSchemaDefinitionsSupplier.getAttnetsENRFieldSchema().getDefault(), currentSchemaDefinitionsSupplier.getSyncnetsENRFieldSchema().getDefault(), Optional.empty(), - Optional.empty(), Optional.empty()); return MultiaddrUtil.fromDiscoveryPeerAsUdp(discoveryPeer).toString(); }) diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java index 1b5266b51d6..d2a1905ecd1 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java @@ -101,8 +101,7 @@ private static DiscoveryPeer socketAddressToDiscoveryPeer( persistentAttestationSubnets, syncCommitteeSubnets, dasTotalCustodySubnetCount, - nextForkDigest, - executionProofSubnets); + nextForkDigest); } private static Optional parseField( From f28297149ce933fd35a95cba0999ec8024fe7e7a Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 14:46:22 +1000 Subject: [PATCH 41/98] fix build Signed-off-by: Gabriel Fukushima --- .../eth2/gossip/subnets/SubnetScorer.java | 34 ++----------------- .../eth2/ActiveEth2P2PNetworkTest.java | 3 ++ .../subnets/PeerSubnetSubscriptionsTest.java | 6 ++++ .../eth2/gossip/subnets/SubnetScorerTest.java | 13 ++++--- .../discovery/discv5/NodeRecordConverter.java | 2 -- 5 files changed, 21 insertions(+), 37 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java index e644643b0a7..3c333e4e998 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorer.java @@ -13,7 +13,6 @@ package tech.pegasys.teku.networking.eth2.gossip.subnets; -import java.util.Optional; import java.util.function.IntUnaryOperator; import org.apache.tuweni.units.bigints.UInt256; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitvector; @@ -42,13 +41,10 @@ public int scoreExistingPeer(final NodeId peerId) { peerSubnetSubscriptions.getSyncCommitteeSubscriptions(peerId); final SszBitvector dataColumnSidecarSubscriptions = peerSubnetSubscriptions.getDataColumnSidecarSubnetSubscriptions(peerId); - final Optional executionProofSubscriptions = - peerSubnetSubscriptions.getExecutionProofSubnetSubscriptions(peerId); return score( attSubscriptions, syncCommitteeSubscriptions, dataColumnSidecarSubscriptions, - executionProofSubscriptions, this::scoreSubnetForExistingPeer); } @@ -58,21 +54,18 @@ public int scoreCandidatePeer(final DiscoveryPeer candidate) { candidate.getPersistentAttestationSubnets(), candidate.getSyncCommitteeSubnets(), peerSubnetSubscriptions.getDataColumnSidecarSubnetSubscriptionsByNodeId( - UInt256.fromBytes(candidate.getNodeId()), candidate.getDasCustodySubnetCount()), - candidate.getExecutionProofSubnets()); + UInt256.fromBytes(candidate.getNodeId()), candidate.getDasCustodySubnetCount())); } // @Override public int scoreCandidatePeer( final SszBitvector attSubnetSubscriptions, final SszBitvector syncCommitteeSubnetSubscriptions, - final SszBitvector dataColumnSidecarSubscriptions, - final Optional executionProofSubnetSubscriptions) { + final SszBitvector dataColumnSidecarSubscriptions) { return score( attSubnetSubscriptions, syncCommitteeSubnetSubscriptions, dataColumnSidecarSubscriptions, - executionProofSubnetSubscriptions, this::scoreSubnetForCandidatePeer); } @@ -80,7 +73,6 @@ private int score( final SszBitvector attestationSubnetSubscriptions, final SszBitvector syncCommitteeSubnetSubscriptions, final SszBitvector dataColumnSidecarSubnetSubscriptions, - final Optional executionProofSubnetSubscriptions, final IntUnaryOperator subscriberCountToScore) { final int attestationSubnetScore = attestationSubnetSubscriptions @@ -119,27 +111,7 @@ private int score( }) .sum(); - final int executionProofSubnetScore = - executionProofSubnetSubscriptions - .map( - executionProof -> - executionProof - .streamAllSetBits() - .filter(peerSubnetSubscriptions::isExecutionProofSubnetRelevant) - .map( - subnetId -> { - int subscriberCount = - peerSubnetSubscriptions.getSubscriberCountForExecutionProofSubnet( - subnetId); - return subscriberCountToScore.applyAsInt(subscriberCount); - }) - .sum()) - .orElse(0); - - return attestationSubnetScore - + syncCommitteeSubnetScore - + dataColumnSidecarSubnetScore - + executionProofSubnetScore; + return attestationSubnetScore + syncCommitteeSubnetScore + dataColumnSidecarSubnetScore; } private int scoreSubnetForExistingPeer(final int subscriberCount) { diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetworkTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetworkTest.java index 516ed3691c3..54102c73c3f 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetworkTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/ActiveEth2P2PNetworkTest.java @@ -80,6 +80,8 @@ public class ActiveEth2P2PNetworkTest { new SubnetSubscriptionService(); private final SubnetSubscriptionService dataColumnSidecarCommitteeSubnetService = new SubnetSubscriptionService(); + private final SubnetSubscriptionService executionProofCommitteeSubnetService = + new SubnetSubscriptionService(); private RecentChainData recentChainData; private final GossipEncoding gossipEncoding = GossipEncoding.SSZ_SNAPPY; private final GossipConfigurator gossipConfigurator = GossipConfigurator.NOOP; @@ -451,6 +453,7 @@ ActiveEth2P2PNetwork createNetwork() { attestationSubnetService, syncCommitteeSubnetService, dataColumnSidecarCommitteeSubnetService, + executionProofCommitteeSubnetService, gossipEncoding, gossipConfigurator, processedAttestationSubscriptionProvider, diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java index 644f4eab9d6..71142ad6393 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java @@ -62,8 +62,12 @@ class PeerSubnetSubscriptionsTest { mock(SyncCommitteeSubnetTopicProvider.class); private final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider = mock(DataColumnSidecarSubnetTopicProvider.class); + private final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider = + mock(ExecutionProofSubnetTopicProvider.class); private final SubnetSubscriptionService syncnetSubscriptions = new SubnetSubscriptionService(); private final SubnetSubscriptionService dataColumnSubscriptions = new SubnetSubscriptionService(); + private final SubnetSubscriptionService executionProofSubscriptions = + new SubnetSubscriptionService(); @BeforeEach public void setUp() { @@ -214,6 +218,8 @@ private PeerSubnetSubscriptions createPeerSubnetSubscriptions() { syncnetSubscriptions, dataColumnSidecarSubnetTopicProvider, dataColumnSubscriptions, + executionProofSubnetTopicProvider, + executionProofSubscriptions, TARGET_SUBSCRIBER_COUNT, subnetPeerCountGauge); } diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java index 6f4307b5f3d..83861169073 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java @@ -45,6 +45,7 @@ class SubnetScorerTest { private final Spec spec = TestSpecFactory.createMinimalAltair(); private final SchemaDefinitions schemaDefinitions = spec.getGenesisSchemaDefinitions(); private static final int DATA_COLUMN_SIDECAR_SUBNET_COUNT = 128; + private static final int EXECUTION_PROOF_SUBNET_COUNT = 8; @Test void shouldScoreCandidatePeerWithNoSubnetsAsZero() { @@ -52,7 +53,8 @@ void shouldScoreCandidatePeerWithNoSubnetsAsZero() { SubnetScorer.create( PeerSubnetSubscriptions.createEmpty( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT))); + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), + SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT))); assertThat( scorer.scoreCandidatePeer( createDiscoveryPeer( @@ -67,7 +69,8 @@ void shouldScoreExistingPeerWithNoSubnetsAsZero() { SubnetScorer.create( PeerSubnetSubscriptions.createEmpty( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT))); + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), + SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT))); assertThat(scorer.scoreExistingPeer(new MockNodeId(1))).isZero(); } @@ -82,7 +85,8 @@ void shouldScoreExistingPeersOnSubnetsWithFewPeersMoreHighly() { SubnetScorer.create( PeerSubnetSubscriptions.builder( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT)) + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), + SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT)) .attestationSubnetSubscriptions( b -> b.addRelevantSubnet(1) @@ -133,7 +137,8 @@ void shouldScoreCandidatePeersOnSubnetsWithFewPeersMoreHighly() { SubnetScorer.create( PeerSubnetSubscriptions.builder( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT)) + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), + SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT)) .attestationSubnetSubscriptions( b -> b.addRelevantSubnet(1) diff --git a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java index d2a1905ecd1..ad6b3b3edd8 100644 --- a/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java +++ b/networking/p2p/src/main/java/tech/pegasys/teku/networking/p2p/discovery/discv5/NodeRecordConverter.java @@ -90,8 +90,6 @@ private static DiscoveryPeer socketAddressToDiscoveryPeer( NEXT_FORK_DIGEST_ENR_FIELD, SszPrimitiveSchemas.BYTES4_SCHEMA::sszDeserialize) .map(SszBytes4::get); - // TODO - see how we gonna define this, if we want to use it - final Optional executionProofSubnets = Optional.empty(); return new DiscoveryPeer( ((Bytes) nodeRecord.get(EnrField.PKEY_SECP256K1)), From 73b6b579099bece4df9c2a42355f1b1f6e023e31 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 9 Sep 2025 15:53:13 +1000 Subject: [PATCH 42/98] fix duplicated line Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/services/beaconchain/BeaconChainController.java | 1 - 1 file changed, 1 deletion(-) 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 0a41f27ba98..9b3517c56db 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 @@ -675,7 +675,6 @@ protected void initKzChain() { ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = new ExecutionProofSubnetSubscriber(spec, p2pNetwork); - new ExecutionProofSubnetSubscriber(spec, p2pNetwork); eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); } From 25c6dfdbc16a95b47b6a8aa5dcef75c54f517890 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 09:17:58 +1000 Subject: [PATCH 43/98] fix method name Signed-off-by: Gabriel Fukushima --- .../teku/services/beaconchain/BeaconChainController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 9b3517c56db..d58c8df9971 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 @@ -654,7 +654,7 @@ public void initAll() { initOperationsReOrgManager(); initValidatorIndexCacheTracker(); initStoredLatestCanonicalBlockUpdater(); - initKzChain(); + initZkChain(); } private void initKeyValueStore() { @@ -666,7 +666,7 @@ protected void initExecutionLayer() { executionLayer = eventChannels.getPublisher(ExecutionLayerChannel.class, beaconAsyncRunner); } - protected void initKzChain() { + protected void initZkChain() { ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { From 99c52dc3e4f47b0d0bc3d4998b7fdcd7b2f38b9f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:02:52 +1000 Subject: [PATCH 44/98] fix init order Signed-off-by: Gabriel Fukushima --- .../beaconchain/BeaconChainController.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) 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 d58c8df9971..9e4c0228ee7 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 @@ -91,7 +91,6 @@ import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSyncCommitteeSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetBackboneSubscriber; -import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.NodeBasedStableSubnetSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.StableSubnetSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubscriptionManager; @@ -195,6 +194,8 @@ import tech.pegasys.teku.statetransition.datacolumns.retriever.DataColumnSidecarRetriever; import tech.pegasys.teku.statetransition.datacolumns.retriever.RecoveringSidecarRetriever; import tech.pegasys.teku.statetransition.datacolumns.retriever.SimpleSidecarRetriever; +import tech.pegasys.teku.statetransition.executionproofs.ExecutionProofManager; +import tech.pegasys.teku.statetransition.executionproofs.ExecutionProofManagerImpl; import tech.pegasys.teku.statetransition.forkchoice.ForkChoice; import tech.pegasys.teku.statetransition.forkchoice.ForkChoiceNotifier; import tech.pegasys.teku.statetransition.forkchoice.ForkChoiceNotifierImpl; @@ -224,6 +225,7 @@ import tech.pegasys.teku.statetransition.validation.BlockGossipValidator; import tech.pegasys.teku.statetransition.validation.BlockValidator; import tech.pegasys.teku.statetransition.validation.DataColumnSidecarGossipValidator; +import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; import tech.pegasys.teku.statetransition.validation.GossipValidationHelper; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; import tech.pegasys.teku.statetransition.validation.ProposerSlashingValidator; @@ -358,6 +360,7 @@ public class BeaconChainController extends Service implements BeaconChainControl protected volatile BlobSidecarManager blobSidecarManager; protected volatile BlobSidecarGossipValidator blobSidecarValidator; protected volatile DataColumnSidecarManager dataColumnSidecarManager; + protected volatile ExecutionProofManager executionProofManager; protected volatile Optional dasCustodySync = Optional.empty(); protected volatile Optional recoveringSidecarRetriever = Optional.empty(); @@ -615,6 +618,7 @@ public void initAll() { initBlobSidecarManager(); initDasSamplerManager(); initDataColumnSidecarManager(); + initZkChain(); initForkChoiceStateProvider(); initForkChoiceNotifier(); initMergeMonitors(); @@ -654,7 +658,6 @@ public void initAll() { initOperationsReOrgManager(); initValidatorIndexCacheTracker(); initStoredLatestCanonicalBlockUpdater(); - initZkChain(); } private void initKeyValueStore() { @@ -670,13 +673,14 @@ protected void initZkChain() { ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { - // final ExecutionProofGossipValidator executionProofGossipValidator = - // ExecutionProofGossipValidator.create(zkConfig); + final ExecutionProofGossipValidator executionProofGossipValidator = + ExecutionProofGossipValidator.create(); - ExecutionProofSubnetSubscriber executionProofSubnetSubscriber = - new ExecutionProofSubnetSubscriber(spec, p2pNetwork); + executionProofManager = new ExecutionProofManagerImpl(executionProofGossipValidator); - eventChannels.subscribe(SlotEventsChannel.class, executionProofSubnetSubscriber); + } + else{ + executionProofManager = ExecutionProofManager.NOOP; } } @@ -1628,6 +1632,8 @@ protected void initP2PNetwork() { .gossipedBlobSidecarProcessor(blobSidecarManager::validateAndPrepareForBlockImport) .gossipedDataColumnSidecarOperationProcessor( dataColumnSidecarManager::onDataColumnSidecarGossip) + .gossipedExecutionProofOperationProcessor( + executionProofManager::onExecutionProofGossip) .gossipedAttestationProcessor(attestationManager::addAttestation) .gossipedAggregateProcessor(attestationManager::addAggregate) .gossipedAttesterSlashingProcessor(attesterSlashingPool::addRemote) From 1c75e48ebdb092a9168aa90a5680aeb8485d4115 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:03:05 +1000 Subject: [PATCH 45/98] rename classes Signed-off-by: Gabriel Fukushima --- .../ExecutionProofManager.java | 54 +++++++++++++++++++ .../ExecutionProofManagerImpl.java | 47 ++++++++++++++++ .../ExecutionProofsManager.java | 16 ------ .../ExecutionProofsManagerImpl.java | 16 ------ 4 files changed, 101 insertions(+), 32 deletions(-) create mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java create mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManagerImpl.java delete mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java delete mode 100644 ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java new file mode 100644 index 00000000000..0dd6e62b86c --- /dev/null +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java @@ -0,0 +1,54 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + +package tech.pegasys.teku.statetransition.executionproofs; + +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; +import tech.pegasys.teku.statetransition.validation.InternalValidationResult; + +import java.util.Optional; + +public interface ExecutionProofManager { + interface ValidExecutionProofListener { + void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + } + + ExecutionProofManager NOOP = + new ExecutionProofManager() { + @Override + public SafeFuture onExecutionProofGossip( + ExecutionProof executionProof, Optional arrivalTimestamp) { + return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); + } + + @Override + public void onExecutionProofPublish( + final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) {} + + @Override + public void subscribeToValidExecutionProofs( + final ValidExecutionProofListener sidecarsListener) {} + }; + + void onExecutionProofPublish(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + + SafeFuture onExecutionProofGossip( + ExecutionProof executionProof, Optional arrivalTimestamp); + + void subscribeToValidExecutionProofs(ExecutionProofManager.ValidExecutionProofListener executionProofListener); + +} 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 new file mode 100644 index 00000000000..02961de97f5 --- /dev/null +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManagerImpl.java @@ -0,0 +1,47 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + +package tech.pegasys.teku.statetransition.executionproofs; + +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; +import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; +import tech.pegasys.teku.statetransition.validation.InternalValidationResult; + +import java.util.Optional; + +public class ExecutionProofManagerImpl implements ExecutionProofManager { + + final ExecutionProofGossipValidator executionProofGossipValidator; + + public ExecutionProofManagerImpl(final ExecutionProofGossipValidator executionProofGossipValidator) { + this.executionProofGossipValidator = executionProofGossipValidator; + } + + @Override + public void onExecutionProofPublish(final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) { + + } + + @Override + public SafeFuture onExecutionProofGossip(final ExecutionProof executionProof, final Optional arrivalTimestamp) { + return null; + } + + @Override + public void subscribeToValidExecutionProofs(final ValidExecutionProofListener executionProofListener) { + + } +} diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java deleted file mode 100644 index 2dfdc088f1b..00000000000 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManager.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2025 - * - * 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. - */ - -package tech.pegasys.teku.statetransition.executionproofs; - -public interface ExecutionProofsManager {} diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java deleted file mode 100644 index cb213587564..00000000000 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofsManagerImpl.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2025 - * - * 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. - */ - -package tech.pegasys.teku.statetransition.executionproofs; - -public class ExecutionProofsManagerImpl implements ExecutionProofsManager {} From c958a32c774fccffc2495a7ec4c21eb012e934d0 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:04:11 +1000 Subject: [PATCH 46/98] add execution proof operation processor for electra and newer forks Signed-off-by: Gabriel Fukushima --- .../GossipForkSubscriptionsElectra.java | 76 ++++++++++++++----- .../versions/GossipForkSubscriptionsFulu.java | 7 +- .../GossipForkSubscriptionsGloas.java | 7 +- 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java index 72a91a1dabc..9aab86b4a4b 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java @@ -15,13 +15,20 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import tech.pegasys.teku.infrastructure.async.AsyncRunner; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipManager; +import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipManager; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; +import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetSubscriptions; +import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; import tech.pegasys.teku.networking.p2p.discovery.DiscoveryNetwork; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -29,33 +36,39 @@ import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SignedContributionAndProof; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.ValidatableSyncCommitteeMessage; import tech.pegasys.teku.spec.datastructures.state.Fork; +import tech.pegasys.teku.spec.datastructures.state.ForkInfo; import tech.pegasys.teku.statetransition.util.DebugDataDumper; import tech.pegasys.teku.storage.client.RecentChainData; public class GossipForkSubscriptionsElectra extends GossipForkSubscriptionsDeneb { + final OperationProcessor executionProofOperationProcessor; + + private ExecutionProofGossipManager executionProofGossipManager; + public GossipForkSubscriptionsElectra( - final Fork fork, - final Spec spec, - final AsyncRunner asyncRunner, - final MetricsSystem metricsSystem, - final DiscoveryNetwork discoveryNetwork, - final RecentChainData recentChainData, - final GossipEncoding gossipEncoding, - final OperationProcessor blockProcessor, - final OperationProcessor blobSidecarProcessor, - final OperationProcessor attestationProcessor, - final OperationProcessor aggregateProcessor, - final OperationProcessor attesterSlashingProcessor, - final OperationProcessor proposerSlashingProcessor, - final OperationProcessor voluntaryExitProcessor, - final OperationProcessor + final Fork fork, + final Spec spec, + final AsyncRunner asyncRunner, + final MetricsSystem metricsSystem, + final DiscoveryNetwork discoveryNetwork, + final RecentChainData recentChainData, + final GossipEncoding gossipEncoding, + final OperationProcessor blockProcessor, + final OperationProcessor blobSidecarProcessor, + final OperationProcessor attestationProcessor, + final OperationProcessor aggregateProcessor, + final OperationProcessor attesterSlashingProcessor, + final OperationProcessor proposerSlashingProcessor, + final OperationProcessor voluntaryExitProcessor, + final OperationProcessor signedContributionAndProofOperationProcessor, - final OperationProcessor + final OperationProcessor syncCommitteeMessageOperationProcessor, - final OperationProcessor + final OperationProcessor signedBlsToExecutionChangeOperationProcessor, - final DebugDataDumper debugDataDumper) { + final DebugDataDumper debugDataDumper, + final OperationProcessor executionProofOperationProcessor) { super( fork, spec, @@ -75,5 +88,32 @@ public GossipForkSubscriptionsElectra( syncCommitteeMessageOperationProcessor, signedBlsToExecutionChangeOperationProcessor, debugDataDumper); + this.executionProofOperationProcessor = executionProofOperationProcessor; } + + @Override + protected void addGossipManagers(final ForkInfo forkInfo, final Bytes4 forkDigest) { + super.addGossipManagers(forkInfo, forkDigest); + addExecutionProofGossipManager(forkInfo, forkDigest); + } + + private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes4 forkDigest) { + executionProofGossipManager = + ExecutionProofGossipManager.create( + recentChainData, + spec, + asyncRunner, + discoveryNetwork, + gossipEncoding, + forkInfo, + forkDigest, + executionProofOperationProcessor, + debugDataDumper); + addGossipManager(executionProofGossipManager); + } + + @Override + public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { + return executionProofGossipManager.publishExecutionProof(executionProof); + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java index 180e4ccce46..7a52ea2c603 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java @@ -27,6 +27,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -68,7 +69,8 @@ public GossipForkSubscriptionsFulu( signedBlsToExecutionChangeOperationProcessor, final OperationProcessor dataColumnSidecarOperationProcessor, final DebugDataDumper debugDataDumper, - final DasGossipLogger dasGossipLogger) { + final DasGossipLogger dasGossipLogger, + final OperationProcessor executionProofOperationProcessor) { super( fork, spec, @@ -87,7 +89,8 @@ public GossipForkSubscriptionsFulu( signedContributionAndProofOperationProcessor, syncCommitteeMessageOperationProcessor, signedBlsToExecutionChangeOperationProcessor, - debugDataDumper); + debugDataDumper, + executionProofOperationProcessor); this.dataColumnSidecarOperationProcessor = dataColumnSidecarOperationProcessor; this.dasGossipLogger = dasGossipLogger; } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java index d0569f5116a..c7f83b2611d 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java @@ -23,6 +23,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -59,7 +60,8 @@ public GossipForkSubscriptionsGloas( signedBlsToExecutionChangeOperationProcessor, final OperationProcessor dataColumnSidecarOperationProcessor, final DebugDataDumper debugDataDumper, - final DasGossipLogger dasGossipLogger) { + final DasGossipLogger dasGossipLogger, + final OperationProcessor executionProcessorOperationProcessor) { super( fork, spec, @@ -80,6 +82,7 @@ public GossipForkSubscriptionsGloas( signedBlsToExecutionChangeOperationProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - dasGossipLogger); + dasGossipLogger, + executionProcessorOperationProcessor); } } From 326e487bdac1040d574d8efd3c066b6bee093be9 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:04:33 +1000 Subject: [PATCH 47/98] get the epoch from recent chain data for the execution proof message Signed-off-by: Gabriel Fukushima --- .../teku/networking/eth2/gossip/forks/GossipForkManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 71106ab231f..2a2c54a2e24 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -193,8 +193,9 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { // for now we don't have a slot in the message data (execution proof) to use // I believe it's safe to just check the current epoch + UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); return publishMessageWithFeedback( - spec.computeStartSlotAtEpoch(currentEpoch.orElseThrow()), + slot, executionProof, "execution proof", GossipForkSubscriptions::publishExecutionProof); From 18c4ceea3afd7c7adcd1e32de2a7d5dccc65b5ac Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:05:24 +1000 Subject: [PATCH 48/98] remove comment Signed-off-by: Gabriel Fukushima --- .../networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index 0d5c038c9ba..baa7d81b785 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -150,8 +150,6 @@ public static PeerSubnetSubscriptions create( .forEach( execSubnet -> { b.addRelevantSubnet(execSubnet); - // Execution payloads are gossiped on the same topic as - // data column sidecars subscribersByTopic .getOrDefault( executionProofSubnetTopicProvider.getTopicForSubnet( From f876a73f467ecbe5b92f02e9f5682652136d13b8 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:05:40 +1000 Subject: [PATCH 49/98] add execution proof gossip manager Signed-off-by: Gabriel Fukushima --- .../gossip/ExecutionProofGossipManager.java | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java new file mode 100644 index 00000000000..c2fc067562d --- /dev/null +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -0,0 +1,174 @@ +package tech.pegasys.teku.networking.eth2.gossip; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import tech.pegasys.teku.infrastructure.async.AsyncRunner; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; +import tech.pegasys.teku.networking.eth2.gossip.topics.OperationMilestoneValidator; +import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; +import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.Eth2TopicHandler; +import tech.pegasys.teku.networking.p2p.gossip.GossipNetwork; +import tech.pegasys.teku.networking.p2p.gossip.TopicChannel; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.SpecVersion; +import tech.pegasys.teku.spec.config.SpecConfigDeneb; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecarSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; +import tech.pegasys.teku.spec.datastructures.state.ForkInfo; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; +import tech.pegasys.teku.statetransition.util.DebugDataDumper; +import tech.pegasys.teku.storage.client.RecentChainData; + +import java.util.Optional; +import java.util.stream.IntStream; + +import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getBlobSidecarSubnetTopicName; +import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getExecutionProofSubnetTopicName; +import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; + +public class ExecutionProofGossipManager implements GossipManager{ + + private static final Logger LOG = LogManager.getLogger(); + + private final Spec spec; + private final GossipNetwork gossipNetwork; + private final GossipEncoding gossipEncoding; + private final Int2ObjectMap> subnetIdToTopicHandler; + private final GossipFailureLogger gossipFailureLogger; + + private final Int2ObjectMap subnetIdToChannel = new Int2ObjectOpenHashMap<>(); + + private ExecutionProofGossipManager(final Spec spec, final GossipNetwork gossipNetwork, final GossipEncoding gossipEncoding, final Int2ObjectMap> subnetIdToTopicHandler, final GossipFailureLogger executionProof) { + this.spec = spec; + this.gossipNetwork = gossipNetwork; + this.gossipEncoding = gossipEncoding; + this.subnetIdToTopicHandler = subnetIdToTopicHandler; + this.gossipFailureLogger = executionProof; + } + + + public static ExecutionProofGossipManager create( + final RecentChainData recentChainData, + final Spec spec, + final AsyncRunner asyncRunner, + final GossipNetwork gossipNetwork, + final GossipEncoding gossipEncoding, + final ForkInfo forkInfo, + final Bytes4 forkDigest, + final OperationProcessor processor, + final DebugDataDumper debugDataDumper) { + final SpecVersion forkSpecVersion = spec.atEpoch(forkInfo.getFork().getEpoch()); + final ExecutionProofSchema gossipType = + SchemaDefinitionsElectra.required(forkSpecVersion.getSchemaDefinitions()) + .getExecutionProofSchema(); + final Int2ObjectMap> subnetIdToTopicHandler = + new Int2ObjectOpenHashMap<>(); + final int executionProofSubnetCount = MAX_EXECUTION_PROOF_SUBNETS.intValue(); // Define this constant as per your configuration + + + IntStream.range(0, executionProofSubnetCount) + .forEach( + subnetId -> { + final Eth2TopicHandler topicHandler = + createExecutionProofTopicHandler( + subnetId, + recentChainData, + spec, + asyncRunner, + processor, + gossipEncoding, + forkInfo, + forkDigest, + gossipType, + debugDataDumper); + subnetIdToTopicHandler.put(subnetId, topicHandler); + }); + return new ExecutionProofGossipManager( + spec, + gossipNetwork, + gossipEncoding, + subnetIdToTopicHandler, + GossipFailureLogger.createNonSuppressing("execution_proof")); + } + + private static Eth2TopicHandler createExecutionProofTopicHandler( + final int subnetId, + final RecentChainData recentChainData, + final Spec spec, + final AsyncRunner asyncRunner, + final OperationProcessor operationProcessor, + final GossipEncoding gossipEncoding, + final ForkInfo forkInfo, + final Bytes4 forkDigest, + final ExecutionProofSchema executionProofSchema, + final DebugDataDumper debugDataDumper) { + return new Eth2TopicHandler<>( + recentChainData, + asyncRunner, + operationProcessor, + gossipEncoding, + forkDigest, + getExecutionProofSubnetTopicName(subnetId), + new OperationMilestoneValidator<>( + recentChainData.getSpec(), + forkInfo.getFork(), + __ -> spec.computeEpochAtSlot(recentChainData.getHeadSlot())), + executionProofSchema, + recentChainData.getSpec().getNetworkingConfig(), + debugDataDumper); + } + + @Override + public void subscribe() { + subnetIdToTopicHandler + .int2ObjectEntrySet() + .forEach( + entry -> { + final Eth2TopicHandler topicHandler = entry.getValue(); + final TopicChannel channel = + gossipNetwork.subscribe(topicHandler.getTopic(), topicHandler); + subnetIdToChannel.put(entry.getIntKey(), channel); + }); + } + + @Override + public void unsubscribe() { + subnetIdToChannel.values().forEach(TopicChannel::close); + subnetIdToChannel.clear(); + } + + @Override + public boolean isEnabledDuringOptimisticSync() { + return true; + } + + /** + * This method is designed to return a future that only completes successfully whenever the gossip + * was succeeded (sent to at least one peer) or failed. + */ + public SafeFuture publishExecutionProof(final ExecutionProof message) { + final int subnetId = spec.computeSubnetForExecutionProof(message).intValue(); + return Optional.ofNullable(subnetIdToChannel.get(subnetId)) + .map(channel -> channel.gossip(gossipEncoding.encode(message))) + .orElse(SafeFuture.failedFuture(new IllegalStateException("Gossip channel not available"))) + .handle( + (__, err) -> { + if (err != null) { + gossipFailureLogger.log(err, Optional.empty()); + } else { + LOG.info( + "Successfully gossiped executionProof {} on {}", + () -> message, + () -> subnetIdToTopicHandler.get(subnetId).getTopic()); + } + return null; + }); + } +} From 4b521f531558d2308ff31cf2dac7a22837fadc84 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 10 Sep 2025 20:06:48 +1000 Subject: [PATCH 50/98] some piping for the operation processor for execution proof Signed-off-by: Gabriel Fukushima --- .../networking/eth2/Eth2P2PNetworkBuilder.java | 18 +++++++++++++++--- .../networking/eth2/Eth2P2PNetworkFactory.java | 17 ++++++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 42523270c21..1d10eafe513 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -86,6 +86,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -147,6 +148,7 @@ public class Eth2P2PNetworkBuilder { protected OperationProcessor gossipedSyncCommitteeMessageProcessor; protected OperationProcessor dataColumnSidecarOperationProcessor; + protected OperationProcessor executionProofOperationProcessor; protected StatusMessageFactory statusMessageFactory; protected KZG kzg; protected boolean recordMessageArrival; @@ -386,7 +388,8 @@ private GossipForkSubscriptions createSubscriptions( gossipedSignedContributionAndProofProcessor, gossipedSyncCommitteeMessageProcessor, gossipedSignedBlsToExecutionChangeProcessor, - debugDataDumper); + debugDataDumper, + executionProofOperationProcessor); case FULU -> new GossipForkSubscriptionsFulu( forkAndSpecMilestone.getFork(), @@ -408,7 +411,8 @@ private GossipForkSubscriptions createSubscriptions( gossipedSignedBlsToExecutionChangeProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - dasGossipLogger); + dasGossipLogger, + executionProofOperationProcessor); case GLOAS -> new GossipForkSubscriptionsGloas( forkAndSpecMilestone.getFork(), @@ -430,7 +434,8 @@ private GossipForkSubscriptions createSubscriptions( gossipedSignedBlsToExecutionChangeProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - dasGossipLogger); + dasGossipLogger, + executionProofOperationProcessor); }; } @@ -760,6 +765,13 @@ public Eth2P2PNetworkBuilder gossipedDataColumnSidecarOperationProcessor( return this; } + public Eth2P2PNetworkBuilder gossipedExecutionProofOperationProcessor( + final OperationProcessor executionProofOperationProcessor) { + checkNotNull(executionProofOperationProcessor); + this.executionProofOperationProcessor = executionProofOperationProcessor; + return this; + } + public Eth2P2PNetworkBuilder metricsSystem(final MetricsSystem metricsSystem) { checkNotNull(metricsSystem); this.metricsSystem = metricsSystem; diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 6502bb60848..9f52cbb9878 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -99,6 +99,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; @@ -163,6 +164,7 @@ public class Eth2P2PNetworkBuilder { protected OperationProcessor syncCommitteeMessageProcessor; protected OperationProcessor signedBlsToExecutionChangeProcessor; protected OperationProcessor dataColumnSidecarOperationProcessor; + protected OperationProcessor executionProofOperationProcessor; protected ProcessedAttestationSubscriptionProvider processedAttestationSubscriptionProvider; protected VerifiedBlockAttestationsSubscriptionProvider verifiedBlockAttestationsSubscriptionProvider; @@ -515,7 +517,8 @@ private GossipForkSubscriptions createSubscriptions( signedContributionAndProofProcessor, syncCommitteeMessageProcessor, signedBlsToExecutionChangeProcessor, - debugDataDumper); + debugDataDumper, + executionProofOperationProcessor); case FULU -> new GossipForkSubscriptionsFulu( forkAndSpecMilestone.getFork(), @@ -537,7 +540,8 @@ private GossipForkSubscriptions createSubscriptions( signedBlsToExecutionChangeProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - DasGossipLogger.NOOP); + DasGossipLogger.NOOP, + executionProofOperationProcessor); case GLOAS -> new GossipForkSubscriptionsGloas( forkAndSpecMilestone.getFork(), @@ -559,7 +563,8 @@ private GossipForkSubscriptions createSubscriptions( signedBlsToExecutionChangeProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - DasGossipLogger.NOOP); + DasGossipLogger.NOOP, + executionProofOperationProcessor); }; } @@ -787,6 +792,12 @@ public Eth2P2PNetworkBuilder gossipedDataColumnSidecarOperationProcessor( this.dataColumnSidecarOperationProcessor = dataColumnSidecarOperationProcessor; return this; } + public Eth2P2PNetworkBuilder gossipedExecutionProofOperationProcessor( + final OperationProcessor executionProofOperationProcessor) { + checkNotNull(executionProofOperationProcessor); + this.executionProofOperationProcessor = executionProofOperationProcessor; + return this; + } public Eth2P2PNetworkBuilder processedAttestationSubscriptionProvider( final ProcessedAttestationSubscriptionProvider processedAttestationSubscriptionProvider) { From 2b55a081cde6bb1c6b0b09b949637335ff774d36 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 11 Sep 2025 10:23:27 +1000 Subject: [PATCH 51/98] change execution gossip manager to rely on subnetsubscription Signed-off-by: Gabriel Fukushima --- .../gossip/ExecutionProofGossipChannel.java | 11 +- .../gossip/ExecutionProofGossipManager.java | 132 +++--------------- .../eth2/gossip/forks/GossipForkManager.java | 4 +- .../gossip/forks/GossipForkSubscriptions.java | 4 +- .../GossipForkSubscriptionsElectra.java | 20 +-- .../ExecutionProofSubnetSubscriber.java | 68 --------- .../ExecutionProofSubnetSubscriptions.java | 96 +++++++++++++ .../ExecutionProofTopicHandler.java | 48 +++++++ 8 files changed, 183 insertions(+), 200 deletions(-) delete mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java create mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java create mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java index 8803a699f34..4466220229f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -16,15 +16,16 @@ import java.util.List; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.events.ChannelInterface; +import tech.pegasys.teku.infrastructure.events.VoidReturningChannelInterface; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; -public interface ExecutionProofGossipChannel extends ChannelInterface { +public interface ExecutionProofGossipChannel extends VoidReturningChannelInterface { - ExecutionProofGossipChannel NOOP = executionProof -> SafeFuture.COMPLETE; + ExecutionProofGossipChannel NOOP = executionProof -> {}; - default SafeFuture publishExecutionProof(final List executionProofs) { - return SafeFuture.allOf(executionProofs.stream().map(this::publishExecutionProof)); + default void publishExecutionProof(final List executionProofs) { + executionProofs.forEach(this::publishExecutionProof); } - SafeFuture publishExecutionProof(ExecutionProof executionProof); + void publishExecutionProof(ExecutionProof executionProof); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index c2fc067562d..aa6246e9793 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -8,6 +8,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; +import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.topics.OperationMilestoneValidator; import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.Eth2TopicHandler; @@ -37,111 +38,22 @@ public class ExecutionProofGossipManager implements GossipManager{ private static final Logger LOG = LogManager.getLogger(); - private final Spec spec; - private final GossipNetwork gossipNetwork; - private final GossipEncoding gossipEncoding; - private final Int2ObjectMap> subnetIdToTopicHandler; - private final GossipFailureLogger gossipFailureLogger; + private final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions; private final Int2ObjectMap subnetIdToChannel = new Int2ObjectOpenHashMap<>(); - private ExecutionProofGossipManager(final Spec spec, final GossipNetwork gossipNetwork, final GossipEncoding gossipEncoding, final Int2ObjectMap> subnetIdToTopicHandler, final GossipFailureLogger executionProof) { - this.spec = spec; - this.gossipNetwork = gossipNetwork; - this.gossipEncoding = gossipEncoding; - this.subnetIdToTopicHandler = subnetIdToTopicHandler; - this.gossipFailureLogger = executionProof; - } - - - public static ExecutionProofGossipManager create( - final RecentChainData recentChainData, - final Spec spec, - final AsyncRunner asyncRunner, - final GossipNetwork gossipNetwork, - final GossipEncoding gossipEncoding, - final ForkInfo forkInfo, - final Bytes4 forkDigest, - final OperationProcessor processor, - final DebugDataDumper debugDataDumper) { - final SpecVersion forkSpecVersion = spec.atEpoch(forkInfo.getFork().getEpoch()); - final ExecutionProofSchema gossipType = - SchemaDefinitionsElectra.required(forkSpecVersion.getSchemaDefinitions()) - .getExecutionProofSchema(); - final Int2ObjectMap> subnetIdToTopicHandler = - new Int2ObjectOpenHashMap<>(); - final int executionProofSubnetCount = MAX_EXECUTION_PROOF_SUBNETS.intValue(); // Define this constant as per your configuration - - - IntStream.range(0, executionProofSubnetCount) - .forEach( - subnetId -> { - final Eth2TopicHandler topicHandler = - createExecutionProofTopicHandler( - subnetId, - recentChainData, - spec, - asyncRunner, - processor, - gossipEncoding, - forkInfo, - forkDigest, - gossipType, - debugDataDumper); - subnetIdToTopicHandler.put(subnetId, topicHandler); - }); - return new ExecutionProofGossipManager( - spec, - gossipNetwork, - gossipEncoding, - subnetIdToTopicHandler, - GossipFailureLogger.createNonSuppressing("execution_proof")); - } - - private static Eth2TopicHandler createExecutionProofTopicHandler( - final int subnetId, - final RecentChainData recentChainData, - final Spec spec, - final AsyncRunner asyncRunner, - final OperationProcessor operationProcessor, - final GossipEncoding gossipEncoding, - final ForkInfo forkInfo, - final Bytes4 forkDigest, - final ExecutionProofSchema executionProofSchema, - final DebugDataDumper debugDataDumper) { - return new Eth2TopicHandler<>( - recentChainData, - asyncRunner, - operationProcessor, - gossipEncoding, - forkDigest, - getExecutionProofSubnetTopicName(subnetId), - new OperationMilestoneValidator<>( - recentChainData.getSpec(), - forkInfo.getFork(), - __ -> spec.computeEpochAtSlot(recentChainData.getHeadSlot())), - executionProofSchema, - recentChainData.getSpec().getNetworkingConfig(), - debugDataDumper); + public ExecutionProofGossipManager(final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions) { + this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; } @Override public void subscribe() { - subnetIdToTopicHandler - .int2ObjectEntrySet() - .forEach( - entry -> { - final Eth2TopicHandler topicHandler = entry.getValue(); - final TopicChannel channel = - gossipNetwork.subscribe(topicHandler.getTopic(), topicHandler); - subnetIdToChannel.put(entry.getIntKey(), channel); - }); + executionProofSubnetSubscriptions.subscribe(); } @Override public void unsubscribe() { - subnetIdToChannel.values().forEach(TopicChannel::close); - subnetIdToChannel.clear(); + executionProofSubnetSubscriptions.unsubscribe(); } @Override @@ -149,26 +61,16 @@ public boolean isEnabledDuringOptimisticSync() { return true; } - /** - * This method is designed to return a future that only completes successfully whenever the gossip - * was succeeded (sent to at least one peer) or failed. - */ - public SafeFuture publishExecutionProof(final ExecutionProof message) { - final int subnetId = spec.computeSubnetForExecutionProof(message).intValue(); - return Optional.ofNullable(subnetIdToChannel.get(subnetId)) - .map(channel -> channel.gossip(gossipEncoding.encode(message))) - .orElse(SafeFuture.failedFuture(new IllegalStateException("Gossip channel not available"))) - .handle( - (__, err) -> { - if (err != null) { - gossipFailureLogger.log(err, Optional.empty()); - } else { - LOG.info( - "Successfully gossiped executionProof {} on {}", - () -> message, - () -> subnetIdToTopicHandler.get(subnetId).getTopic()); - } - return null; - }); + public void subscribeToSubnetId(final int subnetId) { + executionProofSubnetSubscriptions.subscribeToSubnetId(subnetId); + } + + public void unsubscribeFromSubnetId(final int subnetId) { + executionProofSubnetSubscriptions.unsubscribeFromSubnetId(subnetId); } + + public void publish(final ExecutionProof executionProof){ + executionProofSubnetSubscriptions.gossip(executionProof); + } + } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 2a2c54a2e24..4bc6f6d133f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -190,11 +190,11 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo GossipForkSubscriptions::publishDataColumnSidecar); } - public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { + public void publishExecutionProof(final ExecutionProof executionProof) { // for now we don't have a slot in the message data (execution proof) to use // I believe it's safe to just check the current epoch UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); - return publishMessageWithFeedback( + publishMessage( slot, executionProof, "execution proof", diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index e9764ce4af8..0a55e64be6f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -46,8 +46,8 @@ default SafeFuture publishBlobSidecar(final BlobSidecar blobSidecar) { return SafeFuture.COMPLETE; } - default SafeFuture publishExecutionProof(final ExecutionProof executionProof) { - return SafeFuture.COMPLETE; + default void publishExecutionProof(final ExecutionProof executionProof) { + // since Electra for now } void subscribeToAttestationSubnetId(int subnetId); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java index 9aab86b4a4b..0be679cafa5 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java @@ -98,22 +98,26 @@ protected void addGossipManagers(final ForkInfo forkInfo, final Bytes4 forkDiges } private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes4 forkDigest) { - executionProofGossipManager = - ExecutionProofGossipManager.create( - recentChainData, + + ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = + new ExecutionProofSubnetSubscriptions( spec, asyncRunner, discoveryNetwork, gossipEncoding, - forkInfo, - forkDigest, + recentChainData, executionProofOperationProcessor, - debugDataDumper); + debugDataDumper, + forkInfo, + forkDigest + ); + + executionProofGossipManager = new ExecutionProofGossipManager(executionProofSubnetSubscriptions); addGossipManager(executionProofGossipManager); } @Override - public SafeFuture publishExecutionProof(final ExecutionProof executionProof) { - return executionProofGossipManager.publishExecutionProof(executionProof); + public void publishExecutionProof(final ExecutionProof executionProof) { + executionProofGossipManager.publish(executionProof); } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java deleted file mode 100644 index 43079609b33..00000000000 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriber.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2025 - * - * 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. - */ - -package tech.pegasys.teku.networking.eth2.gossip.subnets; - -import static java.util.stream.Collectors.toList; -import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; - -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; -import java.util.Collection; -import java.util.stream.IntStream; -import tech.pegasys.teku.ethereum.events.SlotEventsChannel; -import tech.pegasys.teku.infrastructure.unsigned.UInt64; -import tech.pegasys.teku.networking.eth2.Eth2P2PNetwork; -import tech.pegasys.teku.spec.Spec; - -public class ExecutionProofSubnetSubscriber implements SlotEventsChannel { - private final Eth2P2PNetwork eth2P2PNetwork; - private final Spec spec; - - private IntSet currentSubscribedSubnets = IntSet.of(); - private UInt64 lastEpoch = UInt64.MAX_VALUE; - - public ExecutionProofSubnetSubscriber(final Spec spec, final Eth2P2PNetwork eth2P2PNetwork) { - this.spec = spec; - this.eth2P2PNetwork = eth2P2PNetwork; - } - - private void subscribeToSubnets(final Collection newSubscriptions) { - - IntOpenHashSet newSubscriptionsSet = new IntOpenHashSet(newSubscriptions); - - for (int oldSubnet : currentSubscribedSubnets) { - if (!newSubscriptionsSet.contains(oldSubnet)) { - eth2P2PNetwork.unsubscribeFromExecutionProofSubnetId(oldSubnet); - } - } - - for (int newSubnet : newSubscriptionsSet) { - if (!currentSubscribedSubnets.contains(newSubnet)) { - eth2P2PNetwork.subscribeToExecutionProofSubnetId(newSubnet); - } - } - - currentSubscribedSubnets = newSubscriptionsSet; - } - - @Override - public synchronized void onSlot(final UInt64 slot) { - UInt64 epoch = spec.computeEpochAtSlot(slot); - if (!epoch.equals(lastEpoch)) { - lastEpoch = epoch; - subscribeToSubnets( - IntStream.range(0, MAX_EXECUTION_PROOF_SUBNETS.intValue()).boxed().collect(toList())); - } - } -} diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java new file mode 100644 index 00000000000..316f0a8998e --- /dev/null +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java @@ -0,0 +1,96 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * 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. + */ + +package tech.pegasys.teku.networking.eth2.gossip.subnets; + +import tech.pegasys.teku.infrastructure.async.AsyncRunner; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; +import tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName; +import tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopics; +import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; +import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.DataColumnSidecarTopicHandler; +import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.Eth2TopicHandler; +import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.ExecutionProofTopicHandler; +import tech.pegasys.teku.networking.p2p.gossip.GossipNetwork; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.SpecMilestone; +import tech.pegasys.teku.spec.SpecVersion; +import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; +import tech.pegasys.teku.spec.datastructures.state.ForkInfo; +import tech.pegasys.teku.spec.logic.versions.fulu.helpers.MiscHelpersFulu; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsFulu; +import tech.pegasys.teku.statetransition.util.DebugDataDumper; +import tech.pegasys.teku.storage.client.RecentChainData; + +public class ExecutionProofSubnetSubscriptions extends CommitteeSubnetSubscriptions { + + private final AsyncRunner asyncRunner; + private final RecentChainData recentChainData; + private final OperationProcessor processor; + private final ForkInfo forkInfo; + private final Bytes4 forkDigest; + private final ExecutionProofSchema executionProofSchema; + private final DebugDataDumper debugDataDumper; + + public ExecutionProofSubnetSubscriptions( + final Spec spec, + final AsyncRunner asyncRunner, + final GossipNetwork gossipNetwork, + final GossipEncoding gossipEncoding, + final RecentChainData recentChainData, + final OperationProcessor processor, + final DebugDataDumper debugDataDumper, + final ForkInfo forkInfo, + final Bytes4 forkDigest) { + super(gossipNetwork, gossipEncoding); + this.asyncRunner = asyncRunner; + this.recentChainData = recentChainData; + this.processor = processor; + this.debugDataDumper = debugDataDumper; + this.forkInfo = forkInfo; + this.forkDigest = forkDigest; + final SpecVersion specVersion = + spec.forMilestone(spec.getForkSchedule().getHighestSupportedMilestone()); + this.executionProofSchema = + SchemaDefinitionsElectra.required(specVersion.getSchemaDefinitions()) + .getExecutionProofSchema(); + } + + public SafeFuture gossip(final ExecutionProof executionProof) { + int subnetId = executionProof.getSubnetId().get().intValue(); + final String topic = + GossipTopics.getExecutionProofSubnetTopic(forkDigest, subnetId, gossipEncoding); + return gossipNetwork.gossip(topic, gossipEncoding.encode(executionProof)); + } + + @Override + protected Eth2TopicHandler createTopicHandler(final int subnetId) { + final String topicName = GossipTopicName.getExecutionProofSubnetTopicName(subnetId); + return ExecutionProofTopicHandler.createHandler( + recentChainData, + asyncRunner, + processor, + gossipEncoding, + forkInfo, + forkDigest, + topicName, + executionProofSchema, + debugDataDumper); + } + +} diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java new file mode 100644 index 00000000000..063923e6f25 --- /dev/null +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java @@ -0,0 +1,48 @@ +package tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers; + +import tech.pegasys.teku.infrastructure.async.AsyncRunner; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; +import tech.pegasys.teku.networking.eth2.gossip.topics.OperationMilestoneValidator; +import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; +import tech.pegasys.teku.spec.datastructures.operations.Attestation; +import tech.pegasys.teku.spec.datastructures.operations.AttestationSchema; +import tech.pegasys.teku.spec.datastructures.state.ForkInfo; +import tech.pegasys.teku.statetransition.util.DebugDataDumper; +import tech.pegasys.teku.storage.client.RecentChainData; + +public class ExecutionProofTopicHandler { + + public static Eth2TopicHandler createHandler( + final RecentChainData recentChainData, + final AsyncRunner asyncRunner, + final OperationProcessor operationProcessor, + final GossipEncoding gossipEncoding, + final ForkInfo forkInfo, + final Bytes4 forkDigest, + final String topicName, + final ExecutionProofSchema executionProofSchema, + final DebugDataDumper debugDataDumper) { + final Spec spec = recentChainData.getSpec(); + return new Eth2TopicHandler<>( + recentChainData, + asyncRunner, + operationProcessor, + gossipEncoding, + forkDigest, + topicName, + new OperationMilestoneValidator<>( + recentChainData.getSpec(), + forkInfo.getFork(), + __ -> spec.computeEpochAtSlot(recentChainData.getHeadSlot())), + executionProofSchema, + recentChainData.getSpec().getNetworkingConfig(), + debugDataDumper); + + } + +} From d444c68e8ced1036557d3fb3e72fef953477dd1a Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 11 Sep 2025 10:55:56 +1000 Subject: [PATCH 52/98] spotless Signed-off-by: Gabriel Fukushima --- .../ExecutionProofManager.java | 60 ++++++------ .../ExecutionProofManagerImpl.java | 35 ++++--- .../gossip/ExecutionProofGossipChannel.java | 2 - .../gossip/ExecutionProofGossipManager.java | 97 ++++++++----------- .../eth2/gossip/forks/GossipForkManager.java | 9 +- .../GossipForkSubscriptionsElectra.java | 97 +++++++++---------- .../ExecutionProofSubnetSubscriptions.java | 6 -- .../ExecutionProofTopicHandler.java | 70 +++++++------ .../eth2/Eth2P2PNetworkFactory.java | 1 + .../beaconchain/BeaconChainController.java | 14 ++- 10 files changed, 184 insertions(+), 207 deletions(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java index 0dd6e62b86c..0dcf58fbdaf 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java @@ -13,42 +13,40 @@ package tech.pegasys.teku.statetransition.executionproofs; +import java.util.Optional; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.unsigned.UInt64; -import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; -import java.util.Optional; - public interface ExecutionProofManager { - interface ValidExecutionProofListener { - void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); - } - - ExecutionProofManager NOOP = - new ExecutionProofManager() { - @Override - public SafeFuture onExecutionProofGossip( - ExecutionProof executionProof, Optional arrivalTimestamp) { - return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); - } - - @Override - public void onExecutionProofPublish( - final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) {} - - @Override - public void subscribeToValidExecutionProofs( - final ValidExecutionProofListener sidecarsListener) {} - }; - - void onExecutionProofPublish(ExecutionProof executionProof, RemoteOrigin remoteOrigin); - - SafeFuture onExecutionProofGossip( - ExecutionProof executionProof, Optional arrivalTimestamp); - - void subscribeToValidExecutionProofs(ExecutionProofManager.ValidExecutionProofListener executionProofListener); - + interface ValidExecutionProofListener { + void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + } + + ExecutionProofManager NOOP = + new ExecutionProofManager() { + @Override + public SafeFuture onExecutionProofGossip( + ExecutionProof executionProof, Optional arrivalTimestamp) { + return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); + } + + @Override + public void onExecutionProofPublish( + final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) {} + + @Override + public void subscribeToValidExecutionProofs( + final ValidExecutionProofListener sidecarsListener) {} + }; + + void onExecutionProofPublish(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + + SafeFuture onExecutionProofGossip( + ExecutionProof executionProof, Optional arrivalTimestamp); + + void subscribeToValidExecutionProofs( + ExecutionProofManager.ValidExecutionProofListener executionProofListener); } 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 02961de97f5..3b7d3af777a 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 @@ -13,6 +13,7 @@ package tech.pegasys.teku.statetransition.executionproofs; +import java.util.Optional; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; @@ -20,28 +21,26 @@ import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; -import java.util.Optional; - public class ExecutionProofManagerImpl implements ExecutionProofManager { - final ExecutionProofGossipValidator executionProofGossipValidator; - - public ExecutionProofManagerImpl(final ExecutionProofGossipValidator executionProofGossipValidator) { - this.executionProofGossipValidator = executionProofGossipValidator; - } - - @Override - public void onExecutionProofPublish(final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) { + final ExecutionProofGossipValidator executionProofGossipValidator; - } + public ExecutionProofManagerImpl( + final ExecutionProofGossipValidator executionProofGossipValidator) { + this.executionProofGossipValidator = executionProofGossipValidator; + } - @Override - public SafeFuture onExecutionProofGossip(final ExecutionProof executionProof, final Optional arrivalTimestamp) { - return null; - } + @Override + public void onExecutionProofPublish( + final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) {} - @Override - public void subscribeToValidExecutionProofs(final ValidExecutionProofListener executionProofListener) { + @Override + public SafeFuture onExecutionProofGossip( + final ExecutionProof executionProof, final Optional arrivalTimestamp) { + return null; + } - } + @Override + public void subscribeToValidExecutionProofs( + final ValidExecutionProofListener executionProofListener) {} } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java index 4466220229f..1ada673e061 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -14,8 +14,6 @@ package tech.pegasys.teku.networking.eth2.gossip; import java.util.List; -import tech.pegasys.teku.infrastructure.async.SafeFuture; -import tech.pegasys.teku.infrastructure.events.ChannelInterface; import tech.pegasys.teku.infrastructure.events.VoidReturningChannelInterface; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index aa6246e9793..22655ff4fce 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -1,76 +1,63 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.networking.eth2.gossip; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import tech.pegasys.teku.infrastructure.async.AsyncRunner; -import tech.pegasys.teku.infrastructure.async.SafeFuture; -import tech.pegasys.teku.infrastructure.bytes.Bytes4; -import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; -import tech.pegasys.teku.networking.eth2.gossip.topics.OperationMilestoneValidator; -import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; -import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.Eth2TopicHandler; -import tech.pegasys.teku.networking.p2p.gossip.GossipNetwork; import tech.pegasys.teku.networking.p2p.gossip.TopicChannel; -import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.SpecVersion; -import tech.pegasys.teku.spec.config.SpecConfigDeneb; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecarSchema; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; -import tech.pegasys.teku.spec.datastructures.state.ForkInfo; -import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb; -import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; -import tech.pegasys.teku.statetransition.util.DebugDataDumper; -import tech.pegasys.teku.storage.client.RecentChainData; - -import java.util.Optional; -import java.util.stream.IntStream; - -import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getBlobSidecarSubnetTopicName; -import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getExecutionProofSubnetTopicName; -import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; - -public class ExecutionProofGossipManager implements GossipManager{ - private static final Logger LOG = LogManager.getLogger(); +public class ExecutionProofGossipManager implements GossipManager { - private final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions; + private static final Logger LOG = LogManager.getLogger(); - private final Int2ObjectMap subnetIdToChannel = new Int2ObjectOpenHashMap<>(); + private final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions; - public ExecutionProofGossipManager(final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions) { - this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; - } + private final Int2ObjectMap subnetIdToChannel = new Int2ObjectOpenHashMap<>(); - @Override - public void subscribe() { - executionProofSubnetSubscriptions.subscribe(); - } + public ExecutionProofGossipManager( + final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions) { + this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; + } - @Override - public void unsubscribe() { - executionProofSubnetSubscriptions.unsubscribe(); - } + @Override + public void subscribe() { + executionProofSubnetSubscriptions.subscribe(); + } - @Override - public boolean isEnabledDuringOptimisticSync() { - return true; - } + @Override + public void unsubscribe() { + executionProofSubnetSubscriptions.unsubscribe(); + } - public void subscribeToSubnetId(final int subnetId) { - executionProofSubnetSubscriptions.subscribeToSubnetId(subnetId); - } + @Override + public boolean isEnabledDuringOptimisticSync() { + return true; + } - public void unsubscribeFromSubnetId(final int subnetId) { - executionProofSubnetSubscriptions.unsubscribeFromSubnetId(subnetId); - } + public void subscribeToSubnetId(final int subnetId) { + executionProofSubnetSubscriptions.subscribeToSubnetId(subnetId); + } - public void publish(final ExecutionProof executionProof){ - executionProofSubnetSubscriptions.gossip(executionProof); - } + public void unsubscribeFromSubnetId(final int subnetId) { + executionProofSubnetSubscriptions.unsubscribeFromSubnetId(subnetId); + } + public void publish(final ExecutionProof executionProof) { + executionProofSubnetSubscriptions.gossip(executionProof); + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 4bc6f6d133f..4b34149440d 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -193,12 +193,9 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo public void publishExecutionProof(final ExecutionProof executionProof) { // for now we don't have a slot in the message data (execution proof) to use // I believe it's safe to just check the current epoch - UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); - publishMessage( - slot, - executionProof, - "execution proof", - GossipForkSubscriptions::publishExecutionProof); + UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); + publishMessage( + slot, executionProof, "execution proof", GossipForkSubscriptions::publishExecutionProof); } public void publishSyncCommitteeMessage(final ValidatableSyncCommitteeMessage message) { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java index 0be679cafa5..f6bf7ad15aa 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java @@ -15,12 +15,9 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import tech.pegasys.teku.infrastructure.async.AsyncRunner; -import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.bytes.Bytes4; -import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipManager; import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipManager; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; -import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; import tech.pegasys.teku.networking.p2p.discovery.DiscoveryNetwork; @@ -42,33 +39,33 @@ public class GossipForkSubscriptionsElectra extends GossipForkSubscriptionsDeneb { - final OperationProcessor executionProofOperationProcessor; + final OperationProcessor executionProofOperationProcessor; - private ExecutionProofGossipManager executionProofGossipManager; + private ExecutionProofGossipManager executionProofGossipManager; public GossipForkSubscriptionsElectra( - final Fork fork, - final Spec spec, - final AsyncRunner asyncRunner, - final MetricsSystem metricsSystem, - final DiscoveryNetwork discoveryNetwork, - final RecentChainData recentChainData, - final GossipEncoding gossipEncoding, - final OperationProcessor blockProcessor, - final OperationProcessor blobSidecarProcessor, - final OperationProcessor attestationProcessor, - final OperationProcessor aggregateProcessor, - final OperationProcessor attesterSlashingProcessor, - final OperationProcessor proposerSlashingProcessor, - final OperationProcessor voluntaryExitProcessor, - final OperationProcessor + final Fork fork, + final Spec spec, + final AsyncRunner asyncRunner, + final MetricsSystem metricsSystem, + final DiscoveryNetwork discoveryNetwork, + final RecentChainData recentChainData, + final GossipEncoding gossipEncoding, + final OperationProcessor blockProcessor, + final OperationProcessor blobSidecarProcessor, + final OperationProcessor attestationProcessor, + final OperationProcessor aggregateProcessor, + final OperationProcessor attesterSlashingProcessor, + final OperationProcessor proposerSlashingProcessor, + final OperationProcessor voluntaryExitProcessor, + final OperationProcessor signedContributionAndProofOperationProcessor, - final OperationProcessor + final OperationProcessor syncCommitteeMessageOperationProcessor, - final OperationProcessor + final OperationProcessor signedBlsToExecutionChangeOperationProcessor, - final DebugDataDumper debugDataDumper, - final OperationProcessor executionProofOperationProcessor) { + final DebugDataDumper debugDataDumper, + final OperationProcessor executionProofOperationProcessor) { super( fork, spec, @@ -88,36 +85,36 @@ public GossipForkSubscriptionsElectra( syncCommitteeMessageOperationProcessor, signedBlsToExecutionChangeOperationProcessor, debugDataDumper); - this.executionProofOperationProcessor = executionProofOperationProcessor; + this.executionProofOperationProcessor = executionProofOperationProcessor; } - @Override - protected void addGossipManagers(final ForkInfo forkInfo, final Bytes4 forkDigest) { - super.addGossipManagers(forkInfo, forkDigest); - addExecutionProofGossipManager(forkInfo, forkDigest); - } + @Override + protected void addGossipManagers(final ForkInfo forkInfo, final Bytes4 forkDigest) { + super.addGossipManagers(forkInfo, forkDigest); + addExecutionProofGossipManager(forkInfo, forkDigest); + } - private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes4 forkDigest) { + private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes4 forkDigest) { - ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = - new ExecutionProofSubnetSubscriptions( - spec, - asyncRunner, - discoveryNetwork, - gossipEncoding, - recentChainData, - executionProofOperationProcessor, - debugDataDumper, - forkInfo, - forkDigest - ); + ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = + new ExecutionProofSubnetSubscriptions( + spec, + asyncRunner, + discoveryNetwork, + gossipEncoding, + recentChainData, + executionProofOperationProcessor, + debugDataDumper, + forkInfo, + forkDigest); - executionProofGossipManager = new ExecutionProofGossipManager(executionProofSubnetSubscriptions); - addGossipManager(executionProofGossipManager); - } + executionProofGossipManager = + new ExecutionProofGossipManager(executionProofSubnetSubscriptions); + addGossipManager(executionProofGossipManager); + } - @Override - public void publishExecutionProof(final ExecutionProof executionProof) { - executionProofGossipManager.publish(executionProof); - } + @Override + public void publishExecutionProof(final ExecutionProof executionProof) { + executionProofGossipManager.publish(executionProof); + } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java index 316f0a8998e..e3fbaeb7501 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java @@ -20,20 +20,15 @@ import tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName; import tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopics; import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; -import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.DataColumnSidecarTopicHandler; import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.Eth2TopicHandler; import tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers.ExecutionProofTopicHandler; import tech.pegasys.teku.networking.p2p.gossip.GossipNetwork; import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.SpecVersion; -import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.state.ForkInfo; -import tech.pegasys.teku.spec.logic.versions.fulu.helpers.MiscHelpersFulu; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; -import tech.pegasys.teku.spec.schemas.SchemaDefinitionsFulu; import tech.pegasys.teku.statetransition.util.DebugDataDumper; import tech.pegasys.teku.storage.client.RecentChainData; @@ -92,5 +87,4 @@ protected Eth2TopicHandler createTopicHandler(final int subnetId) { executionProofSchema, debugDataDumper); } - } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java index 063923e6f25..04efc1cf1b6 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/topichandlers/ExecutionProofTopicHandler.java @@ -1,3 +1,16 @@ +/* + * Copyright Consensys Software Inc., 2025 + * + * 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. + */ + package tech.pegasys.teku.networking.eth2.gossip.topics.topichandlers; import tech.pegasys.teku.infrastructure.async.AsyncRunner; @@ -6,43 +19,38 @@ import tech.pegasys.teku.networking.eth2.gossip.topics.OperationMilestoneValidator; import tech.pegasys.teku.networking.eth2.gossip.topics.OperationProcessor; import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; -import tech.pegasys.teku.spec.datastructures.operations.Attestation; -import tech.pegasys.teku.spec.datastructures.operations.AttestationSchema; import tech.pegasys.teku.spec.datastructures.state.ForkInfo; import tech.pegasys.teku.statetransition.util.DebugDataDumper; import tech.pegasys.teku.storage.client.RecentChainData; public class ExecutionProofTopicHandler { - public static Eth2TopicHandler createHandler( - final RecentChainData recentChainData, - final AsyncRunner asyncRunner, - final OperationProcessor operationProcessor, - final GossipEncoding gossipEncoding, - final ForkInfo forkInfo, - final Bytes4 forkDigest, - final String topicName, - final ExecutionProofSchema executionProofSchema, - final DebugDataDumper debugDataDumper) { - final Spec spec = recentChainData.getSpec(); - return new Eth2TopicHandler<>( - recentChainData, - asyncRunner, - operationProcessor, - gossipEncoding, - forkDigest, - topicName, - new OperationMilestoneValidator<>( - recentChainData.getSpec(), - forkInfo.getFork(), - __ -> spec.computeEpochAtSlot(recentChainData.getHeadSlot())), - executionProofSchema, - recentChainData.getSpec().getNetworkingConfig(), - debugDataDumper); - - } - + public static Eth2TopicHandler createHandler( + final RecentChainData recentChainData, + final AsyncRunner asyncRunner, + final OperationProcessor operationProcessor, + final GossipEncoding gossipEncoding, + final ForkInfo forkInfo, + final Bytes4 forkDigest, + final String topicName, + final ExecutionProofSchema executionProofSchema, + final DebugDataDumper debugDataDumper) { + final Spec spec = recentChainData.getSpec(); + return new Eth2TopicHandler<>( + recentChainData, + asyncRunner, + operationProcessor, + gossipEncoding, + forkDigest, + topicName, + new OperationMilestoneValidator<>( + recentChainData.getSpec(), + forkInfo.getFork(), + __ -> spec.computeEpochAtSlot(recentChainData.getHeadSlot())), + executionProofSchema, + recentChainData.getSpec().getNetworkingConfig(), + debugDataDumper); + } } diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 9f52cbb9878..2e3889f6ec0 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -792,6 +792,7 @@ public Eth2P2PNetworkBuilder gossipedDataColumnSidecarOperationProcessor( this.dataColumnSidecarOperationProcessor = dataColumnSidecarOperationProcessor; return this; } + public Eth2P2PNetworkBuilder gossipedExecutionProofOperationProcessor( final OperationProcessor executionProofOperationProcessor) { checkNotNull(executionProofOperationProcessor); 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 9e4c0228ee7..627d311dec1 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 @@ -673,14 +673,13 @@ protected void initZkChain() { ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { - final ExecutionProofGossipValidator executionProofGossipValidator = - ExecutionProofGossipValidator.create(); + final ExecutionProofGossipValidator executionProofGossipValidator = + ExecutionProofGossipValidator.create(); - executionProofManager = new ExecutionProofManagerImpl(executionProofGossipValidator); + executionProofManager = new ExecutionProofManagerImpl(executionProofGossipValidator); - } - else{ - executionProofManager = ExecutionProofManager.NOOP; + } else { + executionProofManager = ExecutionProofManager.NOOP; } } @@ -1632,8 +1631,7 @@ protected void initP2PNetwork() { .gossipedBlobSidecarProcessor(blobSidecarManager::validateAndPrepareForBlockImport) .gossipedDataColumnSidecarOperationProcessor( dataColumnSidecarManager::onDataColumnSidecarGossip) - .gossipedExecutionProofOperationProcessor( - executionProofManager::onExecutionProofGossip) + .gossipedExecutionProofOperationProcessor(executionProofManager::onExecutionProofGossip) .gossipedAttestationProcessor(attestationManager::addAttestation) .gossipedAggregateProcessor(attestationManager::addAggregate) .gossipedAttesterSlashingProcessor(attesterSlashingPool::addRemote) From f67b45ddf7a5dc55d21ee609af757032feee9107 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 11 Sep 2025 11:17:05 +1000 Subject: [PATCH 53/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/networking/eth2/Eth2P2PNetworkBuilder.java | 2 ++ .../eth2/gossip/ExecutionProofGossipManager.java | 9 --------- .../forks/versions/GossipForkSubscriptionsFuluBpo.java | 5 ++++- .../forks/versions/GossipForkSubscriptionsGloasBpo.java | 5 ++++- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 1d10eafe513..30762d9316c 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -465,6 +465,7 @@ private GossipForkSubscriptions createBpoSubscriptions( gossipedSyncCommitteeMessageProcessor, gossipedSignedBlsToExecutionChangeProcessor, dataColumnSidecarOperationProcessor, + executionProofOperationProcessor, debugDataDumper, dasGossipLogger, bpo); @@ -488,6 +489,7 @@ private GossipForkSubscriptions createBpoSubscriptions( gossipedSyncCommitteeMessageProcessor, gossipedSignedBlsToExecutionChangeProcessor, dataColumnSidecarOperationProcessor, + executionProofOperationProcessor, debugDataDumper, dasGossipLogger, bpo); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index 22655ff4fce..add2d89ce50 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -13,22 +13,13 @@ package tech.pegasys.teku.networking.eth2.gossip; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; -import tech.pegasys.teku.networking.p2p.gossip.TopicChannel; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; public class ExecutionProofGossipManager implements GossipManager { - private static final Logger LOG = LogManager.getLogger(); - private final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions; - private final Int2ObjectMap subnetIdToChannel = new Int2ObjectOpenHashMap<>(); - public ExecutionProofGossipManager( final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions) { this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java index 05eded1aaf4..8be823085cd 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java @@ -24,6 +24,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -62,6 +63,7 @@ public GossipForkSubscriptionsFuluBpo( final OperationProcessor signedBlsToExecutionChangeOperationProcessor, final OperationProcessor dataColumnSidecarOperationProcessor, + final OperationProcessor executionProofOperationProcessor, final DebugDataDumper debugDataDumper, final DasGossipLogger dasGossipLogger, final BlobParameters bpo) { @@ -85,7 +87,8 @@ public GossipForkSubscriptionsFuluBpo( signedBlsToExecutionChangeOperationProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - dasGossipLogger); + dasGossipLogger, + executionProofOperationProcessor); this.bpo = bpo; } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java index 6d281efb3ef..741eaddd013 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java @@ -24,6 +24,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -62,6 +63,7 @@ public GossipForkSubscriptionsGloasBpo( final OperationProcessor signedBlsToExecutionChangeOperationProcessor, final OperationProcessor dataColumnSidecarOperationProcessor, + final OperationProcessor executionProofOperationProcessor, final DebugDataDumper debugDataDumper, final DasGossipLogger dasGossipLogger, final BlobParameters bpo) { @@ -85,7 +87,8 @@ public GossipForkSubscriptionsGloasBpo( signedBlsToExecutionChangeOperationProcessor, dataColumnSidecarOperationProcessor, debugDataDumper, - dasGossipLogger); + dasGossipLogger, + executionProofOperationProcessor); this.bpo = bpo; } From 7183bb7b55ddb5414816e1e58102866e58eadd1b Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 11 Sep 2025 16:18:02 +1000 Subject: [PATCH 54/98] add logger Signed-off-by: Gabriel Fukushima --- .../eth2/gossip/ExecutionProofGossipManager.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index add2d89ce50..9a7ceb94824 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -13,11 +13,15 @@ package tech.pegasys.teku.networking.eth2.gossip; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; public class ExecutionProofGossipManager implements GossipManager { + private static final Logger LOG = LogManager.getLogger(); + private final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions; public ExecutionProofGossipManager( @@ -49,6 +53,10 @@ public void unsubscribeFromSubnetId(final int subnetId) { } public void publish(final ExecutionProof executionProof) { - executionProofSubnetSubscriptions.gossip(executionProof); + executionProofSubnetSubscriptions + .gossip(executionProof) + .finish( + __ -> LOG.info(executionProof + " published successfully"), + error -> LOG.info(executionProof + error.getMessage())); } } From 4d078f896962d9054bb1479dd4154e04013ecf19 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 15 Sep 2025 20:27:34 +1000 Subject: [PATCH 55/98] add p2p config to enable execution proofs topic Signed-off-by: Gabriel Fukushima --- .../eth2/Eth2P2PNetworkBuilder.java | 5 +++-- .../teku/networking/eth2/P2PConfig.java | 19 +++++++++++++++++-- .../gossip/topics/Eth2GossipTopicFilter.java | 11 +++++++---- .../eth2/gossip/topics/GossipTopics.java | 11 ++++++++++- .../eth2/peers/Eth2PeerManager.java | 1 + .../topics/Eth2GossipTopicFilterTest.java | 7 +++++-- .../eth2/gossip/topics/GossipTopicsTest.java | 4 +++- .../eth2/Eth2P2PNetworkFactory.java | 5 +++-- .../pegasys/teku/cli/options/P2POptions.java | 13 ++++++++++++- 9 files changed, 61 insertions(+), 15 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 30762d9316c..7b67fc29eed 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -210,7 +210,8 @@ public Eth2P2PNetwork build() { kzg, discoveryNodeIdExtractor, dasTotalCustodyGroupCount, - dasReqRespLogger); + dasReqRespLogger + ); final Collection> eth2RpcMethods = eth2PeerManager.getBeaconChainMethods().all(); rpcMethods.addAll(eth2RpcMethods); @@ -513,7 +514,7 @@ protected DiscoveryNetwork buildNetwork( combinedChainDataClient.getRecentChainData()::getMilestoneByForkDigest); final GossipTopicFilter gossipTopicsFilter = new Eth2GossipTopicFilter( - combinedChainDataClient.getRecentChainData(), gossipEncoding, spec); + combinedChainDataClient.getRecentChainData(), gossipEncoding, spec, config); final NetworkConfig networkConfig = config.getNetworkConfig(); final DiscoveryConfig discoConfig = config.getDiscoveryConfig(); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/P2PConfig.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/P2PConfig.java index 90288dedceb..7f9de4551fb 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/P2PConfig.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/P2PConfig.java @@ -58,6 +58,7 @@ public class P2PConfig { // queries to 5 public static final int DEFAULT_HISTORICAL_DATA_MAX_CONCURRENT_QUERIES = 5; public static final int DEFAULT_HISTORICAL_MAX_QUERY_QUEUE_SIZE = 100_000; + public static final boolean DEFAULT_EXECUTION_PROOF_GOSSIP_ENABLED = false; private final Spec spec; private final NetworkConfig networkConfig; @@ -80,6 +81,7 @@ public class P2PConfig { private final boolean batchVerifyStrictThreadLimitEnabled; private final boolean isGossipBlobsAfterBlockEnabled; private final boolean allTopicsFilterEnabled; + private final boolean executionProofTopicEnabled; private P2PConfig( final Spec spec, @@ -100,7 +102,8 @@ private P2PConfig( final int batchVerifyMaxBatchSize, final boolean batchVerifyStrictThreadLimitEnabled, final boolean allTopicsFilterEnabled, - final boolean isGossipBlobsAfterBlockEnabled) { + final boolean isGossipBlobsAfterBlockEnabled, + final boolean executionProofTopicEnabled) { this.spec = spec; this.networkConfig = networkConfig; this.discoveryConfig = discoveryConfig; @@ -121,6 +124,7 @@ private P2PConfig( this.networkingSpecConfig = spec.getNetworkingConfig(); this.allTopicsFilterEnabled = allTopicsFilterEnabled; this.isGossipBlobsAfterBlockEnabled = isGossipBlobsAfterBlockEnabled; + this.executionProofTopicEnabled = executionProofTopicEnabled; } public static Builder builder() { @@ -208,6 +212,10 @@ public boolean isAllTopicsFilterEnabled() { return allTopicsFilterEnabled; } + public boolean isExecutionProofTopicEnabled() { + return executionProofTopicEnabled; + } + public boolean isGossipBlobsAfterBlockEnabled() { return isGossipBlobsAfterBlockEnabled; } @@ -237,6 +245,7 @@ public static class Builder { private int floodPublishMaxMessageSizeThreshold = DEFAULT_FLOOD_PUBLISH_MAX_MESSAGE_SIZE_THRESHOLD; private boolean gossipBlobsAfterBlockEnabled = DEFAULT_GOSSIP_BLOBS_AFTER_BLOCK_ENABLED; + private boolean executionProofTopicEnabled = DEFAULT_EXECUTION_PROOF_GOSSIP_ENABLED; private Builder() {} @@ -292,7 +301,8 @@ public P2PConfig build() { batchVerifyMaxBatchSize, batchVerifyStrictThreadLimitEnabled, allTopicsFilterEnabled, - gossipBlobsAfterBlockEnabled); + gossipBlobsAfterBlockEnabled, + executionProofTopicEnabled); } private void validate() { @@ -445,5 +455,10 @@ public Builder allTopicsFilterEnabled(final boolean allTopicsFilterEnabled) { this.allTopicsFilterEnabled = allTopicsFilterEnabled; return this; } + + public Builder executionProofTopicEnabled(final boolean executionProofTopicEnabled) { + this.executionProofTopicEnabled = executionProofTopicEnabled; + return this; + } } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java index 648e4ae4b68..5dd8ecd75ee 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java @@ -22,6 +22,7 @@ import org.apache.logging.log4j.Logger; import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.networking.eth2.P2PConfig; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; import tech.pegasys.teku.networking.p2p.libp2p.gossip.GossipTopicFilter; import tech.pegasys.teku.spec.Spec; @@ -33,11 +34,13 @@ public class Eth2GossipTopicFilter implements GossipTopicFilter { private static final Logger LOG = LogManager.getLogger(); private final Spec spec; + private final P2PConfig p2pConfig; private final Supplier> relevantTopics; public Eth2GossipTopicFilter( - final RecentChainData recentChainData, final GossipEncoding gossipEncoding, final Spec spec) { + final RecentChainData recentChainData, final GossipEncoding gossipEncoding, final Spec spec, final P2PConfig p2pConfig) { this.spec = spec; + this.p2pConfig = p2pConfig; relevantTopics = Suppliers.memoize(() -> computeRelevantTopics(recentChainData, gossipEncoding)); } @@ -56,7 +59,7 @@ private Set computeRelevantTopics( final Bytes4 forkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); final SpecMilestone milestone = recentChainData.getMilestoneByForkDigest(forkDigest).orElseThrow(); - final Set topics = getAllTopics(gossipEncoding, forkDigest, spec, milestone); + final Set topics = getAllTopics(gossipEncoding, forkDigest, spec, milestone, p2pConfig); final UInt64 forkEpoch = recentChainData .getBpoForkByForkDigest(forkDigest) @@ -70,7 +73,7 @@ private Set computeRelevantTopics( spec.getForkSchedule().getSpecMilestoneAtEpoch(futureFork.getEpoch()); final Bytes4 futureForkDigest = recentChainData.getForkDigestByMilestone(futureMilestone).orElseThrow(); - topics.addAll(getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone)); + topics.addAll(getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone, p2pConfig)); }); // BPO spec.getBpoForks().stream() @@ -81,7 +84,7 @@ private Set computeRelevantTopics( spec.getForkSchedule().getSpecMilestoneAtEpoch(futureBpoFork.epoch()); final Bytes4 futureForkDigest = recentChainData.getForkDigestByBpoFork(futureBpoFork).orElseThrow(); - topics.addAll(getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone)); + topics.addAll(getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone, p2pConfig)); }); return topics; } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java index 46cf24ffb92..b85e311a2c8 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java @@ -19,9 +19,11 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.P2PConfig; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecMilestone; +import tech.pegasys.teku.spec.config.Constants; import tech.pegasys.teku.spec.constants.NetworkConstants; /** @@ -95,7 +97,8 @@ public static Set getAllTopics( final GossipEncoding gossipEncoding, final Bytes4 forkDigest, final Spec spec, - final SpecMilestone specMilestone) { + final SpecMilestone specMilestone, + final P2PConfig p2pConfig) { final Set topics = new HashSet<>(); for (int i = 0; i < spec.getNetworkingConfig().getAttestationSubnetCount(); i++) { @@ -114,6 +117,12 @@ public static Set getAllTopics( topics.addAll(getAllDataColumnSidecarSubnetTopics(gossipEncoding, forkDigest, spec)); + if(p2pConfig.isExecutionProofTopicEnabled()) { + for (int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + topics.add(getExecutionProofSubnetTopic(forkDigest, i, gossipEncoding)); + } + } + for (GossipTopicName topicName : GossipTopicName.values()) { topics.add(GossipTopics.getTopic(forkDigest, topicName, gossipEncoding)); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java index e27586dcd7e..a74c9d60421 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java @@ -145,6 +145,7 @@ public static Eth2PeerManager create( syncCommitteeSubnetService.subscribeToUpdates( metadataMessagesFactory::updateSyncCommitteeSubnetIds); + return new Eth2PeerManager( spec, asyncRunner, diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java index eca9c14fa1b..68a9366215b 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java @@ -34,6 +34,7 @@ import org.junit.jupiter.api.TestTemplate; import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.networking.eth2.P2PConfig; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecContext; @@ -58,6 +59,7 @@ class Eth2GossipTopicFilterTest { private Bytes4 currentForkDigest; private Eth2GossipTopicFilter filter; private Bytes4 nextForkDigest; + private P2PConfig p2pConfig; @BeforeEach void setUp(final SpecContext specContext) { @@ -66,6 +68,7 @@ void setUp(final SpecContext specContext) { // current milestone is actually the previous milestone currentSpecMilestone = specContext.getSpecMilestone().getPreviousMilestone(); nextSpecMilestone = specContext.getSpecMilestone(); + p2pConfig = P2PConfig.builder().build(); spec = switch (nextSpecMilestone) { case PHASE0, ALTAIR, BELLATRIX, CAPELLA -> @@ -98,7 +101,7 @@ void setUp(final SpecContext specContext) { storageSystem.chainUpdater().initializeGenesis(); recentChainData = spy(storageSystem.recentChainData()); - filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec); + filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec, p2pConfig); currentForkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); nextForkDigest = @@ -222,7 +225,7 @@ void shouldAllowTopicsForBpoForkSameEpochAsFulu() { storageSystem.chainUpdater().initializeGenesis(); recentChainData = spy(storageSystem.recentChainData()); - filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec); + filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec, p2pConfig); currentForkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); nextForkDigest = diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java index 794b24b18d6..431f23a9a87 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java @@ -20,6 +20,7 @@ import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.networking.eth2.P2PConfig; import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; import tech.pegasys.teku.networking.p2p.libp2p.gossip.LibP2PGossipNetworkBuilder; import tech.pegasys.teku.spec.Spec; @@ -58,6 +59,7 @@ public void extractForkDigest_invalid() { public void maxSubscribedTopicsConstantIsLargeEnough() { final SpecMilestone latestMilestone = SpecMilestone.getHighestMilestone(); final Spec spec = TestSpecFactory.createMainnet(latestMilestone); + final P2PConfig p2pConfig = P2PConfig.builder().build(); final StorageSystem storageSystem = InMemoryStorageSystemBuilder.buildDefault(spec); storageSystem.chainUpdater().initializeGenesis(); @@ -76,7 +78,7 @@ public void maxSubscribedTopicsConstantIsLargeEnough() { spec.forMilestone(milestone) .miscHelpers() .computeForkDigest(fork.getCurrentVersion(), genesisValidatorsRoot); - return GossipTopics.getAllTopics(gossipEncoding, forkDigest, spec, milestone) + return GossipTopics.getAllTopics(gossipEncoding, forkDigest, spec, milestone, p2pConfig) .size(); }) .sum(); diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 2e3889f6ec0..733a37bd6f9 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -274,7 +274,8 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { NoOpKZG.INSTANCE, __ -> Optional.of(discoveryNodeId), dasTotalCustodySubnetCount, - DasReqRespLogger.NOOP); + DasReqRespLogger.NOOP + ); List> rpcMethods = eth2PeerManager.getBeaconChainMethods().all().stream() @@ -296,7 +297,7 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { final SyncCommitteeSubnetTopicProvider syncCommitteeTopicProvider = new SyncCommitteeSubnetTopicProvider(recentChainData, gossipEncoding); final GossipTopicFilter gossipTopicsFilter = - new Eth2GossipTopicFilter(recentChainData, gossipEncoding, spec); + new Eth2GossipTopicFilter(recentChainData, gossipEncoding, spec, config); final KeyValueStore keyValueStore = new MemKeyValueStore<>(); final DiscoveryConfig discoConfig = config.getDiscoveryConfig(); final TargetPeerRange targetPeerRange = diff --git a/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java b/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java index ab744609be3..62250712e08 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java @@ -395,6 +395,16 @@ The network interface(s) on which the node listens for P2P communication. fallbackValue = "true") private boolean allTopicsFilterEnabled = P2PConfig.DEFAULT_PEER_ALL_TOPIC_FILTER_ENABLED; + @Option( + names = {"--Xexecution-proof-topics-enabled"}, + paramLabel = "", + showDefaultValue = Visibility.ALWAYS, + description = "Add all topic filtering to p2p configuration.", + arity = "0..1", + hidden = true, + fallbackValue = "true") + private boolean executionProofTopicEnabled = P2PConfig.DEFAULT_EXECUTION_PROOF_GOSSIP_ENABLED; + @Option( names = {"--Xpeer-request-limit"}, paramLabel = "", @@ -592,7 +602,8 @@ public void configure(final TekuConfiguration.Builder builder) { .gossipBlobsAfterBlockEnabled(gossipBlobsAfterBlockEnabled) .dasExtraCustodyGroupCount(dasExtraCustodyGroupCount) .historicalDataMaxConcurrentQueries(historicalDataMaxConcurrentQueries) - .historicalDataMaxQueryQueueSize(historicalDataMaxQueryQueueSize); + .historicalDataMaxQueryQueueSize(historicalDataMaxQueryQueueSize) + .executionProofTopicEnabled(executionProofTopicEnabled); batchVerifyQueueCapacity.ifPresent(b::batchVerifyQueueCapacity); }) .discovery( From 8663868907b230708c2603b34569645895f1c731 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 15 Sep 2025 20:30:14 +1000 Subject: [PATCH 56/98] add log and subscribe to valid EP Signed-off-by: Gabriel Fukushima --- .../teku/services/beaconchain/BeaconChainController.java | 4 ++++ 1 file changed, 4 insertions(+) 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 627d311dec1..c295cdc0dd5 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 @@ -466,6 +466,9 @@ protected void startServices() { blobSidecar -> recentBlobSidecarsFetcher.cancelRecentBlobSidecarRequest( new BlobIdentifier(blobSidecar.getBlockRoot(), blobSidecar.getIndex()))); + executionProofManager.subscribeToValidExecutionProofs( + (executionProof, remoteOrigin) -> LOG.info("Received valid execution proof: {}", executionProof) + ); final Optional network = beaconConfig.eth2NetworkConfig().getEth2Network(); if (network.isPresent() && network.get() == Eth2Network.EPHEMERY) { @@ -670,6 +673,7 @@ protected void initExecutionLayer() { } protected void initZkChain() { + LOG.debug("BeaconChainController.initZkChain()"); ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { From 17cab7383ae8eab1b17aaf5f152d887ddb7a27a3 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 15 Sep 2025 20:30:27 +1000 Subject: [PATCH 57/98] subscribe overrides for electra Signed-off-by: Gabriel Fukushima --- .../forks/versions/GossipForkSubscriptionsElectra.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java index f6bf7ad15aa..60b26d1f278 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java @@ -117,4 +117,14 @@ private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes public void publishExecutionProof(final ExecutionProof executionProof) { executionProofGossipManager.publish(executionProof); } + + @Override + public void subscribeToExecutionProofSubnet(final int subnetId) { + executionProofGossipManager.subscribeToSubnetId(subnetId); + } + + @Override + public void unsubscribeFromExecutionProofSubnet(final int subnetId) { + executionProofGossipManager.unsubscribeFromSubnetId(subnetId); + } } From 2fbcc2d1f92c5c0607e8bf5eeb4645595b5a9c46 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 15 Sep 2025 20:31:54 +1000 Subject: [PATCH 58/98] spotless Signed-off-by: Gabriel Fukushima --- .../teku/networking/eth2/Eth2P2PNetworkBuilder.java | 3 +-- .../eth2/gossip/topics/Eth2GossipTopicFilter.java | 11 ++++++++--- .../networking/eth2/gossip/topics/GossipTopics.java | 8 ++++---- .../teku/networking/eth2/peers/Eth2PeerManager.java | 1 - .../eth2/gossip/topics/GossipTopicsTest.java | 3 ++- .../teku/networking/eth2/Eth2P2PNetworkFactory.java | 3 +-- .../services/beaconchain/BeaconChainController.java | 6 +++--- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 7b67fc29eed..6acca693894 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -210,8 +210,7 @@ public Eth2P2PNetwork build() { kzg, discoveryNodeIdExtractor, dasTotalCustodyGroupCount, - dasReqRespLogger - ); + dasReqRespLogger); final Collection> eth2RpcMethods = eth2PeerManager.getBeaconChainMethods().all(); rpcMethods.addAll(eth2RpcMethods); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java index 5dd8ecd75ee..c00f1047c5a 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilter.java @@ -38,7 +38,10 @@ public class Eth2GossipTopicFilter implements GossipTopicFilter { private final Supplier> relevantTopics; public Eth2GossipTopicFilter( - final RecentChainData recentChainData, final GossipEncoding gossipEncoding, final Spec spec, final P2PConfig p2pConfig) { + final RecentChainData recentChainData, + final GossipEncoding gossipEncoding, + final Spec spec, + final P2PConfig p2pConfig) { this.spec = spec; this.p2pConfig = p2pConfig; relevantTopics = @@ -73,7 +76,8 @@ private Set computeRelevantTopics( spec.getForkSchedule().getSpecMilestoneAtEpoch(futureFork.getEpoch()); final Bytes4 futureForkDigest = recentChainData.getForkDigestByMilestone(futureMilestone).orElseThrow(); - topics.addAll(getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone, p2pConfig)); + topics.addAll( + getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone, p2pConfig)); }); // BPO spec.getBpoForks().stream() @@ -84,7 +88,8 @@ private Set computeRelevantTopics( spec.getForkSchedule().getSpecMilestoneAtEpoch(futureBpoFork.epoch()); final Bytes4 futureForkDigest = recentChainData.getForkDigestByBpoFork(futureBpoFork).orElseThrow(); - topics.addAll(getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone, p2pConfig)); + topics.addAll( + getAllTopics(gossipEncoding, futureForkDigest, spec, futureMilestone, p2pConfig)); }); return topics; } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java index b85e311a2c8..71debc16f7c 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopics.java @@ -117,10 +117,10 @@ public static Set getAllTopics( topics.addAll(getAllDataColumnSidecarSubnetTopics(gossipEncoding, forkDigest, spec)); - if(p2pConfig.isExecutionProofTopicEnabled()) { - for (int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { - topics.add(getExecutionProofSubnetTopic(forkDigest, i, gossipEncoding)); - } + if (p2pConfig.isExecutionProofTopicEnabled()) { + for (int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + topics.add(getExecutionProofSubnetTopic(forkDigest, i, gossipEncoding)); + } } for (GossipTopicName topicName : GossipTopicName.values()) { diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java index a74c9d60421..e27586dcd7e 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/peers/Eth2PeerManager.java @@ -145,7 +145,6 @@ public static Eth2PeerManager create( syncCommitteeSubnetService.subscribeToUpdates( metadataMessagesFactory::updateSyncCommitteeSubnetIds); - return new Eth2PeerManager( spec, asyncRunner, diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java index 431f23a9a87..5b6cb9e4cdb 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java @@ -78,7 +78,8 @@ public void maxSubscribedTopicsConstantIsLargeEnough() { spec.forMilestone(milestone) .miscHelpers() .computeForkDigest(fork.getCurrentVersion(), genesisValidatorsRoot); - return GossipTopics.getAllTopics(gossipEncoding, forkDigest, spec, milestone, p2pConfig) + return GossipTopics.getAllTopics( + gossipEncoding, forkDigest, spec, milestone, p2pConfig) .size(); }) .sum(); diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 733a37bd6f9..88468ab0ed2 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -274,8 +274,7 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { NoOpKZG.INSTANCE, __ -> Optional.of(discoveryNodeId), dasTotalCustodySubnetCount, - DasReqRespLogger.NOOP - ); + DasReqRespLogger.NOOP); List> rpcMethods = eth2PeerManager.getBeaconChainMethods().all().stream() 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 c295cdc0dd5..3a080b64f78 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 @@ -467,8 +467,8 @@ protected void startServices() { recentBlobSidecarsFetcher.cancelRecentBlobSidecarRequest( new BlobIdentifier(blobSidecar.getBlockRoot(), blobSidecar.getIndex()))); executionProofManager.subscribeToValidExecutionProofs( - (executionProof, remoteOrigin) -> LOG.info("Received valid execution proof: {}", executionProof) - ); + (executionProof, remoteOrigin) -> + LOG.info("Received valid execution proof: {}", executionProof)); final Optional network = beaconConfig.eth2NetworkConfig().getEth2Network(); if (network.isPresent() && network.get() == Eth2Network.EPHEMERY) { @@ -673,7 +673,7 @@ protected void initExecutionLayer() { } protected void initZkChain() { - LOG.debug("BeaconChainController.initZkChain()"); + LOG.debug("BeaconChainController.initZkChain()"); ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); if (zkConfig.isStatelessValidationEnabled()) { From 8c52ef5351544d6dccf2d8055bfc592f53a9b185 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:01:07 +1000 Subject: [PATCH 59/98] fix executionProof container and schema Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 44 ++++++++++++++++--- .../execution/ExecutionProofSchema.java | 11 +++-- .../teku/spec/util/DataStructureUtil.java | 1 + 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 9b6e3b0a1a0..5196f7b5c43 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -13,41 +13,73 @@ package tech.pegasys.teku.spec.datastructures.execution; +import org.apache.tuweni.bytes.Bytes32; import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; +import tech.pegasys.teku.infrastructure.ssz.collections.impl.SszByteListImpl; import tech.pegasys.teku.infrastructure.ssz.containers.Container4; +import tech.pegasys.teku.infrastructure.ssz.containers.Container5; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; +import tech.pegasys.teku.infrastructure.ssz.tree.LeafNode; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeUtil; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; + +import java.util.List; + +import static java.lang.Long.toHexString; +import static tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema.SSZ_SCHEMA; public class ExecutionProof - extends Container4 { + extends Container5 { public ExecutionProof(final ExecutionProofSchema schema, final TreeNode node) { super(schema, node); } + public static ExecutionProof create(final UInt64 slot) { + return SSZ_SCHEMA.create( + SszBytes32.of(Bytes32.fromHexString(toHexString(slot.longValue()))), + SszBytes32.of(Bytes32.fromHexString(toHexString(slot.longValue()))), + SszUInt64.of(UInt64.ONE), + SszUInt64.ZERO, + SSZ_SCHEMA.getProofDataSchema().fromBytes(Bytes32.ZERO)); + } + + public static final ExecutionProof DUMMY_PROOF = SSZ_SCHEMA.create( + SszBytes32.of(Bytes32.ZERO), + SszBytes32.of(Bytes32.ZERO), + SszUInt64.of(UInt64.ONE), + SszUInt64.ZERO, + SSZ_SCHEMA.getProofDataSchema().fromBytes(Bytes32.ZERO)); + public ExecutionProof( final ExecutionProofSchema schema, + final SszBytes32 blockRoot, final SszBytes32 blockHash, final SszUInt64 subnetId, final SszUInt64 version, final SszByteList proofData) { - super(schema, blockHash, subnetId, version, proofData); + super(schema, blockRoot, blockHash, subnetId, version, proofData); } - public SszBytes32 getBlockHash() { + public SszBytes32 getBlockRoot() { return getField0(); } + public SszBytes32 getBlockHash() { + return getField1(); + } + public SszUInt64 getSubnetId() { - return getField1(); + return getField2(); } public SszUInt64 getVersion() { - return getField2(); + return getField3(); } public SszByteList getProofData() { - return getField3(); + return getField4(); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index ce4da42c884..b47dbc787c8 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -15,6 +15,7 @@ import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema5; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; @@ -22,7 +23,7 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProofSchema - extends ContainerSchema4 { + extends ContainerSchema5 { // as per suggestion in https://github.com/Consensys/teku/pull/9853#discussion_r2329217191 // this may change in when we get smaller proofs @@ -31,18 +32,22 @@ public class ExecutionProofSchema public ExecutionProofSchema() { super( "ExecutionProof", + namedSchema("block_root", SszPrimitiveSchemas.BYTES32_SCHEMA), namedSchema("block_hash", SszPrimitiveSchemas.BYTES32_SCHEMA), namedSchema("subnet_id", SszPrimitiveSchemas.UINT64_SCHEMA), namedSchema("version", SszPrimitiveSchemas.UINT64_SCHEMA), namedSchema("proof_data", SszByteListSchema.create(MAX_PROOF_DATA_SIZE))); } + final static ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); + public ExecutionProof create( + final SszBytes32 blockRoot, final SszBytes32 blockHash, final SszUInt64 subnetId, final SszUInt64 version, final SszByteList proofData) { - return new ExecutionProof(this, blockHash, subnetId, version, proofData); + return new ExecutionProof(this, blockRoot, blockHash, subnetId, version, proofData); } @Override @@ -52,6 +57,6 @@ public ExecutionProof createFromBackingNode(final TreeNode node) { @SuppressWarnings("unchecked") public SszByteListSchema getProofDataSchema() { - return (SszByteListSchema) getFieldSchema3(); + return (SszByteListSchema) getFieldSchema4(); } } diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index b4bd4a8be0b..99d1a3edf9b 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -3099,6 +3099,7 @@ public ExecutionProof randomExecutionProof() { final ExecutionProofSchema executionProofSchema = schemaDefinitionsElectra.getExecutionProofSchema(); return executionProofSchema.create( + SszBytes32.of(randomBytes32()), SszBytes32.of(randomBytes32()), SszUInt64.of(randomUInt64()), SszUInt64.of(randomUInt64()), From 3794d3602cbec4fc3c84fd4b71f201fd4c2b4784 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:04:15 +1000 Subject: [PATCH 60/98] fix EP manager and add logs to gossip validator Signed-off-by: Gabriel Fukushima --- .../ExecutionProofManager.java | 8 +++++--- .../ExecutionProofManagerImpl.java | 19 +++++++++++++++++-- .../ExecutionProofGossipValidator.java | 3 +++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java index 0dcf58fbdaf..eba035dffd0 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java @@ -21,9 +21,7 @@ import tech.pegasys.teku.statetransition.validation.InternalValidationResult; public interface ExecutionProofManager { - interface ValidExecutionProofListener { - void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); - } + ExecutionProofManager NOOP = new ExecutionProofManager() { @@ -49,4 +47,8 @@ SafeFuture onExecutionProofGossip( void subscribeToValidExecutionProofs( ExecutionProofManager.ValidExecutionProofListener executionProofListener); + + interface ValidExecutionProofListener { + void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + } } 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 3b7d3af777a..af444b0352f 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 @@ -14,9 +14,15 @@ package tech.pegasys.teku.statetransition.executionproofs; import java.util.Optional; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import tech.pegasys.teku.ethereum.events.SlotEventsChannel; import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.subscribers.Subscribers; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; +import tech.pegasys.teku.statetransition.blobs.BlobSidecarManager; import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; @@ -24,10 +30,15 @@ public class ExecutionProofManagerImpl implements ExecutionProofManager { final ExecutionProofGossipValidator executionProofGossipValidator; +// final ExecutionProofGossipValidator executionProofGossipValidator; + private final Subscribers receivedExecutionProofSubscribers = + Subscribers.create(true); + private static final Logger LOG = LogManager.getLogger(); public ExecutionProofManagerImpl( final ExecutionProofGossipValidator executionProofGossipValidator) { this.executionProofGossipValidator = executionProofGossipValidator; + } @Override @@ -37,10 +48,14 @@ public void onExecutionProofPublish( @Override public SafeFuture onExecutionProofGossip( final ExecutionProof executionProof, final Optional arrivalTimestamp) { - return null; + LOG.debug("Received execution proof for block {}", executionProof); + return executionProofGossipValidator + .validate(executionProof, executionProof.getSubnetId().get()); } @Override public void subscribeToValidExecutionProofs( - final ValidExecutionProofListener executionProofListener) {} + final ValidExecutionProofListener executionProofListener) { + receivedExecutionProofSubscribers.subscribe(executionProofListener); + } } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 6a1fab38973..344c65e37df 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -40,6 +40,8 @@ public ExecutionProofGossipValidator(final Set receivedValidExec public SafeFuture validate( final ExecutionProof executionProof, final UInt64 subnetId) { + + //TODO need to check for other validations done in the prototype and spec if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { LOG.warn("ExecutionProof subnetId does not match the gossip subnetId"); return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); @@ -51,6 +53,7 @@ public SafeFuture validate( } // Validated the execution proof + LOG.debug("Received and validated execution proof for block {}", executionProof.getBlockHash()); receivedValidExecutionProofSet.add(executionProof); return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); } From 452bda98d009ac59d525911d8bec6ddcf788e4e5 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:04:36 +1000 Subject: [PATCH 61/98] add debug log on publish EP Signed-off-by: Gabriel Fukushima --- .../teku/networking/eth2/gossip/forks/GossipForkManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 4b34149440d..4dff227433e 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -193,6 +193,7 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo public void publishExecutionProof(final ExecutionProof executionProof) { // for now we don't have a slot in the message data (execution proof) to use // I believe it's safe to just check the current epoch + LOG.debug("Publishing execution proof for slot {}", executionProof); UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); publishMessage( slot, executionProof, "execution proof", GossipForkSubscriptions::publishExecutionProof); From 119a957312bf872107611e1febdad8933dc9c73c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:05:12 +1000 Subject: [PATCH 62/98] add log to topic creation Signed-off-by: Gabriel Fukushima --- .../gossip/subnets/ExecutionProofSubnetSubscriptions.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java index e3fbaeb7501..6d73e205e76 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java @@ -13,6 +13,8 @@ package tech.pegasys.teku.networking.eth2.gossip.subnets; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.bytes.Bytes4; @@ -25,6 +27,7 @@ import tech.pegasys.teku.networking.p2p.gossip.GossipNetwork; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecVersion; +import tech.pegasys.teku.spec.config.Constants; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.state.ForkInfo; @@ -42,6 +45,8 @@ public class ExecutionProofSubnetSubscriptions extends CommitteeSubnetSubscripti private final ExecutionProofSchema executionProofSchema; private final DebugDataDumper debugDataDumper; + private static final Logger LOG = LogManager.getLogger(); + public ExecutionProofSubnetSubscriptions( final Spec spec, final AsyncRunner asyncRunner, @@ -75,6 +80,7 @@ public SafeFuture gossip(final ExecutionProof executionProof) { @Override protected Eth2TopicHandler createTopicHandler(final int subnetId) { + LOG.debug("Creating ExecutionProof topic handler for subnet {}", subnetId); final String topicName = GossipTopicName.getExecutionProofSubnetTopicName(subnetId); return ExecutionProofTopicHandler.createHandler( recentChainData, From 833f80307004f6d0269c4383ad198b3a8acba054 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:10:35 +1000 Subject: [PATCH 63/98] remove dummy proof creation Signed-off-by: Gabriel Fukushima --- .../datastructures/execution/ExecutionProof.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 5196f7b5c43..49ae430c7c1 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -37,21 +37,6 @@ public ExecutionProof(final ExecutionProofSchema schema, final TreeNode node) { super(schema, node); } - public static ExecutionProof create(final UInt64 slot) { - return SSZ_SCHEMA.create( - SszBytes32.of(Bytes32.fromHexString(toHexString(slot.longValue()))), - SszBytes32.of(Bytes32.fromHexString(toHexString(slot.longValue()))), - SszUInt64.of(UInt64.ONE), - SszUInt64.ZERO, - SSZ_SCHEMA.getProofDataSchema().fromBytes(Bytes32.ZERO)); - } - - public static final ExecutionProof DUMMY_PROOF = SSZ_SCHEMA.create( - SszBytes32.of(Bytes32.ZERO), - SszBytes32.of(Bytes32.ZERO), - SszUInt64.of(UInt64.ONE), - SszUInt64.ZERO, - SSZ_SCHEMA.getProofDataSchema().fromBytes(Bytes32.ZERO)); public ExecutionProof( final ExecutionProofSchema schema, From d039fcfa90ceefcf7759d176f9e1a070fd1669e4 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:11:15 +1000 Subject: [PATCH 64/98] subscribe to max subnet for EP Signed-off-by: Gabriel Fukushima --- .../networking/eth2/gossip/ExecutionProofGossipManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index 9a7ceb94824..48320cf8b76 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -16,6 +16,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetSubscriptions; +import tech.pegasys.teku.spec.config.Constants; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; public class ExecutionProofGossipManager implements GossipManager { @@ -27,6 +28,10 @@ public class ExecutionProofGossipManager implements GossipManager { public ExecutionProofGossipManager( final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions) { this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; + + for(int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + executionProofSubnetSubscriptions.subscribeToSubnetId(i); + } } @Override @@ -53,6 +58,7 @@ public void unsubscribeFromSubnetId(final int subnetId) { } public void publish(final ExecutionProof executionProof) { + LOG.debug("Publishing from ExecutionProofGossipManager"); executionProofSubnetSubscriptions .gossip(executionProof) .finish( From dd715aa157c2e3fb034f86dc8052b9340528b29f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:13:26 +1000 Subject: [PATCH 65/98] add gossip channel publisher to networkAsync runner Signed-off-by: Gabriel Fukushima --- .../teku/services/beaconchain/BeaconChainController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 3a080b64f78..fb6b705c0af 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 @@ -87,6 +87,7 @@ import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.BlockGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.DataColumnSidecarGossipChannel; +import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSubnetsSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSyncCommitteeSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber; @@ -675,7 +676,9 @@ protected void initExecutionLayer() { protected void initZkChain() { LOG.debug("BeaconChainController.initZkChain()"); ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); - +// comment for now this will be used in the future +// final ExecutionProofGossipChannel executionProofGossipChannel = + eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); if (zkConfig.isStatelessValidationEnabled()) { final ExecutionProofGossipValidator executionProofGossipValidator = ExecutionProofGossipValidator.create(); From cd0d23197b6df1afb3a3d1a31b73643301b799e2 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:15:01 +1000 Subject: [PATCH 66/98] spotless Signed-off-by: Gabriel Fukushima --- .../execution/ExecutionProof.java | 18 +++------------- .../execution/ExecutionProofSchema.java | 6 +++--- .../ExecutionProofManager.java | 7 +++---- .../ExecutionProofManagerImpl.java | 21 ++++++++----------- .../ExecutionProofGossipValidator.java | 4 ++-- .../gossip/ExecutionProofGossipManager.java | 4 ++-- .../eth2/gossip/forks/GossipForkManager.java | 2 +- .../ExecutionProofSubnetSubscriptions.java | 5 ++--- .../beaconchain/BeaconChainController.java | 6 +++--- 9 files changed, 28 insertions(+), 45 deletions(-) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java index 49ae430c7c1..de04e6d5e3d 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProof.java @@ -13,22 +13,11 @@ package tech.pegasys.teku.spec.datastructures.execution; -import org.apache.tuweni.bytes.Bytes32; import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; -import tech.pegasys.teku.infrastructure.ssz.collections.impl.SszByteListImpl; -import tech.pegasys.teku.infrastructure.ssz.containers.Container4; import tech.pegasys.teku.infrastructure.ssz.containers.Container5; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; -import tech.pegasys.teku.infrastructure.ssz.tree.LeafNode; import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; -import tech.pegasys.teku.infrastructure.ssz.tree.TreeUtil; -import tech.pegasys.teku.infrastructure.unsigned.UInt64; - -import java.util.List; - -import static java.lang.Long.toHexString; -import static tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema.SSZ_SCHEMA; public class ExecutionProof extends Container5 { @@ -37,7 +26,6 @@ public ExecutionProof(final ExecutionProofSchema schema, final TreeNode node) { super(schema, node); } - public ExecutionProof( final ExecutionProofSchema schema, final SszBytes32 blockRoot, @@ -52,9 +40,9 @@ public SszBytes32 getBlockRoot() { return getField0(); } - public SszBytes32 getBlockHash() { - return getField1(); - } + public SszBytes32 getBlockHash() { + return getField1(); + } public SszUInt64 getSubnetId() { return getField2(); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java index b47dbc787c8..0d3482cef52 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/execution/ExecutionProofSchema.java @@ -14,7 +14,6 @@ package tech.pegasys.teku.spec.datastructures.execution; import tech.pegasys.teku.infrastructure.ssz.collections.SszByteList; -import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema4; import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema5; import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; @@ -23,7 +22,8 @@ import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; public class ExecutionProofSchema - extends ContainerSchema5 { + extends ContainerSchema5< + ExecutionProof, SszBytes32, SszBytes32, SszUInt64, SszUInt64, SszByteList> { // as per suggestion in https://github.com/Consensys/teku/pull/9853#discussion_r2329217191 // this may change in when we get smaller proofs @@ -39,7 +39,7 @@ public ExecutionProofSchema() { namedSchema("proof_data", SszByteListSchema.create(MAX_PROOF_DATA_SIZE))); } - final static ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); + static final ExecutionProofSchema SSZ_SCHEMA = new ExecutionProofSchema(); public ExecutionProof create( final SszBytes32 blockRoot, diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java index eba035dffd0..14d3f745f04 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/executionproofs/ExecutionProofManager.java @@ -22,7 +22,6 @@ public interface ExecutionProofManager { - ExecutionProofManager NOOP = new ExecutionProofManager() { @Override @@ -48,7 +47,7 @@ SafeFuture onExecutionProofGossip( void subscribeToValidExecutionProofs( ExecutionProofManager.ValidExecutionProofListener executionProofListener); - interface ValidExecutionProofListener { - void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); - } + interface ValidExecutionProofListener { + void onNewValidExecutionProof(ExecutionProof executionProof, RemoteOrigin remoteOrigin); + } } 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 af444b0352f..4e279617019 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 @@ -14,15 +14,12 @@ package tech.pegasys.teku.statetransition.executionproofs; import java.util.Optional; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import tech.pegasys.teku.ethereum.events.SlotEventsChannel; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.subscribers.Subscribers; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; -import tech.pegasys.teku.statetransition.blobs.BlobSidecarManager; import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; import tech.pegasys.teku.statetransition.validation.ExecutionProofGossipValidator; import tech.pegasys.teku.statetransition.validation.InternalValidationResult; @@ -30,15 +27,15 @@ public class ExecutionProofManagerImpl implements ExecutionProofManager { final ExecutionProofGossipValidator executionProofGossipValidator; -// final ExecutionProofGossipValidator executionProofGossipValidator; - private final Subscribers receivedExecutionProofSubscribers = - Subscribers.create(true); + // final ExecutionProofGossipValidator executionProofGossipValidator; + private final Subscribers receivedExecutionProofSubscribers = + Subscribers.create(true); + + private static final Logger LOG = LogManager.getLogger(); - private static final Logger LOG = LogManager.getLogger(); public ExecutionProofManagerImpl( final ExecutionProofGossipValidator executionProofGossipValidator) { this.executionProofGossipValidator = executionProofGossipValidator; - } @Override @@ -48,14 +45,14 @@ public void onExecutionProofPublish( @Override public SafeFuture onExecutionProofGossip( final ExecutionProof executionProof, final Optional arrivalTimestamp) { - LOG.debug("Received execution proof for block {}", executionProof); - return executionProofGossipValidator - .validate(executionProof, executionProof.getSubnetId().get()); + LOG.debug("Received execution proof for block {}", executionProof); + return executionProofGossipValidator.validate( + executionProof, executionProof.getSubnetId().get()); } @Override public void subscribeToValidExecutionProofs( final ValidExecutionProofListener executionProofListener) { - receivedExecutionProofSubscribers.subscribe(executionProofListener); + receivedExecutionProofSubscribers.subscribe(executionProofListener); } } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 344c65e37df..0f9511c6c72 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -41,7 +41,7 @@ public ExecutionProofGossipValidator(final Set receivedValidExec public SafeFuture validate( final ExecutionProof executionProof, final UInt64 subnetId) { - //TODO need to check for other validations done in the prototype and spec + // TODO need to check for other validations done in the prototype and spec if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { LOG.warn("ExecutionProof subnetId does not match the gossip subnetId"); return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); @@ -53,7 +53,7 @@ public SafeFuture validate( } // Validated the execution proof - LOG.debug("Received and validated execution proof for block {}", executionProof.getBlockHash()); + LOG.debug("Received and validated execution proof for block {}", executionProof.getBlockHash()); receivedValidExecutionProofSet.add(executionProof); return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index 48320cf8b76..3dd295afebb 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -29,7 +29,7 @@ public ExecutionProofGossipManager( final ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions) { this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; - for(int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + for (int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { executionProofSubnetSubscriptions.subscribeToSubnetId(i); } } @@ -58,7 +58,7 @@ public void unsubscribeFromSubnetId(final int subnetId) { } public void publish(final ExecutionProof executionProof) { - LOG.debug("Publishing from ExecutionProofGossipManager"); + LOG.debug("Publishing from ExecutionProofGossipManager"); executionProofSubnetSubscriptions .gossip(executionProof) .finish( diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index 4dff227433e..a7a82acfd12 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -193,7 +193,7 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo public void publishExecutionProof(final ExecutionProof executionProof) { // for now we don't have a slot in the message data (execution proof) to use // I believe it's safe to just check the current epoch - LOG.debug("Publishing execution proof for slot {}", executionProof); + LOG.debug("Publishing execution proof for slot {}", executionProof); UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); publishMessage( slot, executionProof, "execution proof", GossipForkSubscriptions::publishExecutionProof); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java index 6d73e205e76..04e60c9ea81 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetSubscriptions.java @@ -27,7 +27,6 @@ import tech.pegasys.teku.networking.p2p.gossip.GossipNetwork; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecVersion; -import tech.pegasys.teku.spec.config.Constants; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.execution.ExecutionProofSchema; import tech.pegasys.teku.spec.datastructures.state.ForkInfo; @@ -45,7 +44,7 @@ public class ExecutionProofSubnetSubscriptions extends CommitteeSubnetSubscripti private final ExecutionProofSchema executionProofSchema; private final DebugDataDumper debugDataDumper; - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LogManager.getLogger(); public ExecutionProofSubnetSubscriptions( final Spec spec, @@ -80,7 +79,7 @@ public SafeFuture gossip(final ExecutionProof executionProof) { @Override protected Eth2TopicHandler createTopicHandler(final int subnetId) { - LOG.debug("Creating ExecutionProof topic handler for subnet {}", subnetId); + LOG.debug("Creating ExecutionProof topic handler for subnet {}", subnetId); final String topicName = GossipTopicName.getExecutionProofSubnetTopicName(subnetId); return ExecutionProofTopicHandler.createHandler( recentChainData, 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 fb6b705c0af..c99f6f46a64 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 @@ -676,9 +676,9 @@ protected void initExecutionLayer() { protected void initZkChain() { LOG.debug("BeaconChainController.initZkChain()"); ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); -// comment for now this will be used in the future -// final ExecutionProofGossipChannel executionProofGossipChannel = - eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); + // comment for now this will be used in the future + // final ExecutionProofGossipChannel executionProofGossipChannel = + eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); if (zkConfig.isStatelessValidationEnabled()) { final ExecutionProofGossipValidator executionProofGossipValidator = ExecutionProofGossipValidator.create(); From 9bb5afc2c126789cd95b1c1857f20183b813de28 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:50:45 +1000 Subject: [PATCH 67/98] fix tests to pass spec to p2p config builder Signed-off-by: Gabriel Fukushima --- .../eth2/gossip/topics/Eth2GossipTopicFilterTest.java | 4 ++-- .../teku/networking/eth2/gossip/topics/GossipTopicsTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java index 68a9366215b..7ef0d3725a2 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java @@ -68,7 +68,7 @@ void setUp(final SpecContext specContext) { // current milestone is actually the previous milestone currentSpecMilestone = specContext.getSpecMilestone().getPreviousMilestone(); nextSpecMilestone = specContext.getSpecMilestone(); - p2pConfig = P2PConfig.builder().build(); + spec = switch (nextSpecMilestone) { case PHASE0, ALTAIR, BELLATRIX, CAPELLA -> @@ -96,7 +96,7 @@ void setUp(final SpecContext specContext) { new BlobScheduleEntry( bpoFork.epoch(), bpoFork.maxBlobsPerBlock()))))); }; - + p2pConfig = P2PConfig.builder().specProvider(spec).build(); final StorageSystem storageSystem = InMemoryStorageSystemBuilder.buildDefault(spec); storageSystem.chainUpdater().initializeGenesis(); diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java index 5b6cb9e4cdb..38ab3cb19fa 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/GossipTopicsTest.java @@ -59,7 +59,7 @@ public void extractForkDigest_invalid() { public void maxSubscribedTopicsConstantIsLargeEnough() { final SpecMilestone latestMilestone = SpecMilestone.getHighestMilestone(); final Spec spec = TestSpecFactory.createMainnet(latestMilestone); - final P2PConfig p2pConfig = P2PConfig.builder().build(); + final P2PConfig p2pConfig = P2PConfig.builder().specProvider(spec).build(); final StorageSystem storageSystem = InMemoryStorageSystemBuilder.buildDefault(spec); storageSystem.chainUpdater().initializeGenesis(); From a27e8e731fba6fa27636fbddf6f4312b1e755f86 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 13:57:42 +1000 Subject: [PATCH 68/98] remove unnecessary log Signed-off-by: Gabriel Fukushima --- .../teku/networking/eth2/gossip/ExecutionProofGossipManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index 3dd295afebb..67d393841c1 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -58,7 +58,6 @@ public void unsubscribeFromSubnetId(final int subnetId) { } public void publish(final ExecutionProof executionProof) { - LOG.debug("Publishing from ExecutionProofGossipManager"); executionProofSubnetSubscriptions .gossip(executionProof) .finish( From b294185db0e648ee76447b5a62b30eec7bafab5c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 18:43:53 +1000 Subject: [PATCH 69/98] change executionProofGossipManager in GossipForkSubscriptionsElectra to optional Signed-off-by: Gabriel Fukushima --- .../GossipForkSubscriptionsElectra.java | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java index 60b26d1f278..a22b16e02ba 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java @@ -13,6 +13,8 @@ package tech.pegasys.teku.networking.eth2.gossip.forks.versions; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.hyperledger.besu.plugin.services.MetricsSystem; import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.bytes.Bytes4; @@ -37,12 +39,15 @@ import tech.pegasys.teku.statetransition.util.DebugDataDumper; import tech.pegasys.teku.storage.client.RecentChainData; +import java.util.Optional; + public class GossipForkSubscriptionsElectra extends GossipForkSubscriptionsDeneb { final OperationProcessor executionProofOperationProcessor; - private ExecutionProofGossipManager executionProofGossipManager; - + private Optional executionProofGossipManager; + private final boolean isExecutionProofTopicEnabled; + private static final Logger LOG = LogManager.getLogger(); public GossipForkSubscriptionsElectra( final Fork fork, final Spec spec, @@ -65,7 +70,8 @@ public GossipForkSubscriptionsElectra( final OperationProcessor signedBlsToExecutionChangeOperationProcessor, final DebugDataDumper debugDataDumper, - final OperationProcessor executionProofOperationProcessor) { + final OperationProcessor executionProofOperationProcessor, + final boolean isExecutionProofTopicEnabled) { super( fork, spec, @@ -86,6 +92,7 @@ public GossipForkSubscriptionsElectra( signedBlsToExecutionChangeOperationProcessor, debugDataDumper); this.executionProofOperationProcessor = executionProofOperationProcessor; + this.isExecutionProofTopicEnabled = isExecutionProofTopicEnabled; } @Override @@ -95,36 +102,43 @@ protected void addGossipManagers(final ForkInfo forkInfo, final Bytes4 forkDiges } private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes4 forkDigest) { + if (isExecutionProofTopicEnabled) { + LOG.debug("Creating ExecutionProofSubnetSubscriptions"); + ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = + new ExecutionProofSubnetSubscriptions( + spec, + asyncRunner, + discoveryNetwork, + gossipEncoding, + recentChainData, + executionProofOperationProcessor, + debugDataDumper, + forkInfo, + forkDigest); - ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = - new ExecutionProofSubnetSubscriptions( - spec, - asyncRunner, - discoveryNetwork, - gossipEncoding, - recentChainData, - executionProofOperationProcessor, - debugDataDumper, - forkInfo, - forkDigest); + executionProofGossipManager = Optional.of( + new ExecutionProofGossipManager(executionProofSubnetSubscriptions)); + addGossipManager(executionProofGossipManager.get()); + } + else{ + LOG.debug("Using ExecutionProofGossipManager.NOOP"); + executionProofGossipManager = Optional.empty(); + } - executionProofGossipManager = - new ExecutionProofGossipManager(executionProofSubnetSubscriptions); - addGossipManager(executionProofGossipManager); } @Override public void publishExecutionProof(final ExecutionProof executionProof) { - executionProofGossipManager.publish(executionProof); + executionProofGossipManager.ifPresent(epGossipManager -> epGossipManager.publish(executionProof)); } @Override public void subscribeToExecutionProofSubnet(final int subnetId) { - executionProofGossipManager.subscribeToSubnetId(subnetId); + executionProofGossipManager.ifPresent(epGossipManager -> epGossipManager.subscribeToSubnetId(subnetId)); } @Override public void unsubscribeFromExecutionProofSubnet(final int subnetId) { - executionProofGossipManager.unsubscribeFromSubnetId(subnetId); + executionProofGossipManager.ifPresent(epGossipManager -> epGossipManager.unsubscribeFromSubnetId(subnetId)); } } From ff7f802f1b71f8a33d88b8ef057d2b53d5739e6d Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 18:44:25 +1000 Subject: [PATCH 70/98] executionProofGossipManager created based on the p2p flag Signed-off-by: Gabriel Fukushima --- .../networking/eth2/Eth2P2PNetworkBuilder.java | 15 ++++++++++----- .../versions/GossipForkSubscriptionsFulu.java | 6 ++++-- .../versions/GossipForkSubscriptionsFuluBpo.java | 6 ++++-- .../versions/GossipForkSubscriptionsGloas.java | 6 ++++-- .../versions/GossipForkSubscriptionsGloasBpo.java | 6 ++++-- .../networking/eth2/Eth2P2PNetworkFactory.java | 9 ++++++--- 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 6acca693894..5af41da1550 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -389,7 +389,8 @@ private GossipForkSubscriptions createSubscriptions( gossipedSyncCommitteeMessageProcessor, gossipedSignedBlsToExecutionChangeProcessor, debugDataDumper, - executionProofOperationProcessor); + executionProofOperationProcessor, + config.isExecutionProofTopicEnabled()); case FULU -> new GossipForkSubscriptionsFulu( forkAndSpecMilestone.getFork(), @@ -412,7 +413,8 @@ private GossipForkSubscriptions createSubscriptions( dataColumnSidecarOperationProcessor, debugDataDumper, dasGossipLogger, - executionProofOperationProcessor); + executionProofOperationProcessor, + config.isExecutionProofTopicEnabled()); case GLOAS -> new GossipForkSubscriptionsGloas( forkAndSpecMilestone.getFork(), @@ -435,7 +437,8 @@ private GossipForkSubscriptions createSubscriptions( dataColumnSidecarOperationProcessor, debugDataDumper, dasGossipLogger, - executionProofOperationProcessor); + executionProofOperationProcessor, + config.isExecutionProofTopicEnabled()); }; } @@ -468,7 +471,8 @@ private GossipForkSubscriptions createBpoSubscriptions( executionProofOperationProcessor, debugDataDumper, dasGossipLogger, - bpo); + bpo, + config.isExecutionProofTopicEnabled()); case GLOAS -> new GossipForkSubscriptionsGloasBpo( forkAndSpecMilestone.getFork(), @@ -492,7 +496,8 @@ private GossipForkSubscriptions createBpoSubscriptions( executionProofOperationProcessor, debugDataDumper, dasGossipLogger, - bpo); + bpo, + config.isExecutionProofTopicEnabled()); default -> throw new IllegalStateException( "BPO is not supported for: " + forkAndSpecMilestone.getSpecMilestone()); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java index 7a52ea2c603..a6e3239a433 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFulu.java @@ -70,7 +70,8 @@ public GossipForkSubscriptionsFulu( final OperationProcessor dataColumnSidecarOperationProcessor, final DebugDataDumper debugDataDumper, final DasGossipLogger dasGossipLogger, - final OperationProcessor executionProofOperationProcessor) { + final OperationProcessor executionProofOperationProcessor, + final boolean isExecutionProofTopicEnabled) { super( fork, spec, @@ -90,7 +91,8 @@ public GossipForkSubscriptionsFulu( syncCommitteeMessageOperationProcessor, signedBlsToExecutionChangeOperationProcessor, debugDataDumper, - executionProofOperationProcessor); + executionProofOperationProcessor, + isExecutionProofTopicEnabled); this.dataColumnSidecarOperationProcessor = dataColumnSidecarOperationProcessor; this.dasGossipLogger = dasGossipLogger; } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java index 8be823085cd..cf37c47525b 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsFuluBpo.java @@ -66,7 +66,8 @@ public GossipForkSubscriptionsFuluBpo( final OperationProcessor executionProofOperationProcessor, final DebugDataDumper debugDataDumper, final DasGossipLogger dasGossipLogger, - final BlobParameters bpo) { + final BlobParameters bpo, + final boolean isExecutionProofTopicEnabled) { super( fork, spec, @@ -88,7 +89,8 @@ public GossipForkSubscriptionsFuluBpo( dataColumnSidecarOperationProcessor, debugDataDumper, dasGossipLogger, - executionProofOperationProcessor); + executionProofOperationProcessor, + isExecutionProofTopicEnabled); this.bpo = bpo; } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java index c7f83b2611d..a234bbbd232 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java @@ -61,7 +61,8 @@ public GossipForkSubscriptionsGloas( final OperationProcessor dataColumnSidecarOperationProcessor, final DebugDataDumper debugDataDumper, final DasGossipLogger dasGossipLogger, - final OperationProcessor executionProcessorOperationProcessor) { + final OperationProcessor executionProcessorOperationProcessor, + final boolean isExecutionProofTopicEnabled) { super( fork, spec, @@ -83,6 +84,7 @@ public GossipForkSubscriptionsGloas( dataColumnSidecarOperationProcessor, debugDataDumper, dasGossipLogger, - executionProcessorOperationProcessor); + executionProcessorOperationProcessor, + isExecutionProofTopicEnabled); } } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java index 741eaddd013..c453b3e2764 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java @@ -66,7 +66,8 @@ public GossipForkSubscriptionsGloasBpo( final OperationProcessor executionProofOperationProcessor, final DebugDataDumper debugDataDumper, final DasGossipLogger dasGossipLogger, - final BlobParameters bpo) { + final BlobParameters bpo, + final boolean isExecutionProofTopicEnabled) { super( fork, spec, @@ -88,7 +89,8 @@ public GossipForkSubscriptionsGloasBpo( dataColumnSidecarOperationProcessor, debugDataDumper, dasGossipLogger, - executionProofOperationProcessor); + executionProofOperationProcessor, + isExecutionProofTopicEnabled); this.bpo = bpo; } diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 88468ab0ed2..d3a1c02c3a0 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -518,7 +518,8 @@ private GossipForkSubscriptions createSubscriptions( syncCommitteeMessageProcessor, signedBlsToExecutionChangeProcessor, debugDataDumper, - executionProofOperationProcessor); + executionProofOperationProcessor, + generateConfig().isExecutionProofTopicEnabled()); case FULU -> new GossipForkSubscriptionsFulu( forkAndSpecMilestone.getFork(), @@ -541,7 +542,8 @@ private GossipForkSubscriptions createSubscriptions( dataColumnSidecarOperationProcessor, debugDataDumper, DasGossipLogger.NOOP, - executionProofOperationProcessor); + executionProofOperationProcessor, + generateConfig().isExecutionProofTopicEnabled()); case GLOAS -> new GossipForkSubscriptionsGloas( forkAndSpecMilestone.getFork(), @@ -564,7 +566,8 @@ private GossipForkSubscriptions createSubscriptions( dataColumnSidecarOperationProcessor, debugDataDumper, DasGossipLogger.NOOP, - executionProofOperationProcessor); + executionProofOperationProcessor, + generateConfig().isExecutionProofTopicEnabled()); }; } From 43ee8a26737fdac5891f3fd05fa891fd0ad32f36 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 18 Sep 2025 18:44:54 +1000 Subject: [PATCH 71/98] spotless Signed-off-by: Gabriel Fukushima --- .../eth2/Eth2P2PNetworkBuilder.java | 2 +- .../GossipForkSubscriptionsElectra.java | 57 ++++++++++--------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 5af41da1550..374606d534f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -497,7 +497,7 @@ private GossipForkSubscriptions createBpoSubscriptions( debugDataDumper, dasGossipLogger, bpo, - config.isExecutionProofTopicEnabled()); + config.isExecutionProofTopicEnabled()); default -> throw new IllegalStateException( "BPO is not supported for: " + forkAndSpecMilestone.getSpecMilestone()); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java index a22b16e02ba..7dbee4eb244 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsElectra.java @@ -13,6 +13,7 @@ package tech.pegasys.teku.networking.eth2.gossip.forks.versions; +import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -39,15 +40,14 @@ import tech.pegasys.teku.statetransition.util.DebugDataDumper; import tech.pegasys.teku.storage.client.RecentChainData; -import java.util.Optional; - public class GossipForkSubscriptionsElectra extends GossipForkSubscriptionsDeneb { final OperationProcessor executionProofOperationProcessor; private Optional executionProofGossipManager; private final boolean isExecutionProofTopicEnabled; - private static final Logger LOG = LogManager.getLogger(); + private static final Logger LOG = LogManager.getLogger(); + public GossipForkSubscriptionsElectra( final Fork fork, final Spec spec, @@ -102,43 +102,44 @@ protected void addGossipManagers(final ForkInfo forkInfo, final Bytes4 forkDiges } private void addExecutionProofGossipManager(final ForkInfo forkInfo, final Bytes4 forkDigest) { - if (isExecutionProofTopicEnabled) { - LOG.debug("Creating ExecutionProofSubnetSubscriptions"); - ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = - new ExecutionProofSubnetSubscriptions( - spec, - asyncRunner, - discoveryNetwork, - gossipEncoding, - recentChainData, - executionProofOperationProcessor, - debugDataDumper, - forkInfo, - forkDigest); - - executionProofGossipManager = Optional.of( - new ExecutionProofGossipManager(executionProofSubnetSubscriptions)); - addGossipManager(executionProofGossipManager.get()); - } - else{ - LOG.debug("Using ExecutionProofGossipManager.NOOP"); - executionProofGossipManager = Optional.empty(); - } + if (isExecutionProofTopicEnabled) { + LOG.debug("Creating ExecutionProofSubnetSubscriptions"); + ExecutionProofSubnetSubscriptions executionProofSubnetSubscriptions = + new ExecutionProofSubnetSubscriptions( + spec, + asyncRunner, + discoveryNetwork, + gossipEncoding, + recentChainData, + executionProofOperationProcessor, + debugDataDumper, + forkInfo, + forkDigest); + executionProofGossipManager = + Optional.of(new ExecutionProofGossipManager(executionProofSubnetSubscriptions)); + addGossipManager(executionProofGossipManager.get()); + } else { + LOG.debug("Using ExecutionProofGossipManager.NOOP"); + executionProofGossipManager = Optional.empty(); + } } @Override public void publishExecutionProof(final ExecutionProof executionProof) { - executionProofGossipManager.ifPresent(epGossipManager -> epGossipManager.publish(executionProof)); + executionProofGossipManager.ifPresent( + epGossipManager -> epGossipManager.publish(executionProof)); } @Override public void subscribeToExecutionProofSubnet(final int subnetId) { - executionProofGossipManager.ifPresent(epGossipManager -> epGossipManager.subscribeToSubnetId(subnetId)); + executionProofGossipManager.ifPresent( + epGossipManager -> epGossipManager.subscribeToSubnetId(subnetId)); } @Override public void unsubscribeFromExecutionProofSubnet(final int subnetId) { - executionProofGossipManager.ifPresent(epGossipManager -> epGossipManager.unsubscribeFromSubnetId(subnetId)); + executionProofGossipManager.ifPresent( + epGossipManager -> epGossipManager.unsubscribeFromSubnetId(subnetId)); } } From 780a2dae185415e90452ead3d66069e0f57b385d Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 19 Sep 2025 14:41:20 +1000 Subject: [PATCH 72/98] add tests for ExecutionProofs subnets Signed-off-by: Gabriel Fukushima --- .../topics/Eth2GossipTopicFilterTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java index 7ef0d3725a2..4a4669f6506 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java @@ -21,6 +21,7 @@ import static tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding.SSZ_SNAPPY; import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getAttestationSubnetTopicName; import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getBlobSidecarSubnetTopicName; +import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getExecutionProofSubnetTopicName; import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopicName.getSyncCommitteeSubnetTopicName; import static tech.pegasys.teku.spec.SpecMilestone.DENEB; import static tech.pegasys.teku.spec.SpecMilestone.ELECTRA; @@ -41,6 +42,7 @@ import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.TestSpecInvocationContextProvider.SpecContext; import tech.pegasys.teku.spec.config.BlobScheduleEntry; +import tech.pegasys.teku.spec.config.Constants; import tech.pegasys.teku.spec.config.SpecConfig; import tech.pegasys.teku.spec.config.SpecConfigDeneb; import tech.pegasys.teku.spec.logic.versions.fulu.helpers.BlobParameters; @@ -240,6 +242,32 @@ void shouldAllowTopicsForBpoForkSameEpochAsFulu() { assertThat(filter.isRelevantTopic(bpoTopic)).isTrue(); } + @TestTemplate + void shouldNotConsiderExecutionProofSubnetsRelevantByDefault() { + assumeThat(nextSpecMilestone).isEqualTo(ELECTRA); + for(int i = 0; i< Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + assertThat( + filter.isRelevantTopic( + getTopicName(getExecutionProofSubnetTopicName( i)))) + .isFalse(); + } + } + + @TestTemplate + void shouldConsiderExecutionProofSubnetsRelevantWhenEnabled() { + P2PConfig p2pConfigOverwritten = P2PConfig.builder().specProvider(spec).executionProofTopicEnabled(true).build(); + filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec, p2pConfigOverwritten); + assumeThat(nextSpecMilestone).isEqualTo(ELECTRA); + for(int i = 0; i< Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + assertThat( + filter.isRelevantTopic( + getTopicName(getExecutionProofSubnetTopicName( i)))) + .isTrue(); + } + } + + + private String getTopicName(final GossipTopicName name) { return GossipTopics.getTopic(currentForkDigest, name, SSZ_SNAPPY); } From 45bb603a9fda627b1ddad4a9da11f210b14b9727 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 19 Sep 2025 14:41:33 +1000 Subject: [PATCH 73/98] spotless Signed-off-by: Gabriel Fukushima --- .../topics/Eth2GossipTopicFilterTest.java | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java index 4a4669f6506..887d42feb89 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/topics/Eth2GossipTopicFilterTest.java @@ -242,31 +242,26 @@ void shouldAllowTopicsForBpoForkSameEpochAsFulu() { assertThat(filter.isRelevantTopic(bpoTopic)).isTrue(); } - @TestTemplate - void shouldNotConsiderExecutionProofSubnetsRelevantByDefault() { - assumeThat(nextSpecMilestone).isEqualTo(ELECTRA); - for(int i = 0; i< Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { - assertThat( - filter.isRelevantTopic( - getTopicName(getExecutionProofSubnetTopicName( i)))) - .isFalse(); - } + @TestTemplate + void shouldNotConsiderExecutionProofSubnetsRelevantByDefault() { + assumeThat(nextSpecMilestone).isEqualTo(ELECTRA); + for (int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + assertThat(filter.isRelevantTopic(getTopicName(getExecutionProofSubnetTopicName(i)))) + .isFalse(); } + } - @TestTemplate - void shouldConsiderExecutionProofSubnetsRelevantWhenEnabled() { - P2PConfig p2pConfigOverwritten = P2PConfig.builder().specProvider(spec).executionProofTopicEnabled(true).build(); - filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec, p2pConfigOverwritten); - assumeThat(nextSpecMilestone).isEqualTo(ELECTRA); - for(int i = 0; i< Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { - assertThat( - filter.isRelevantTopic( - getTopicName(getExecutionProofSubnetTopicName( i)))) - .isTrue(); - } + @TestTemplate + void shouldConsiderExecutionProofSubnetsRelevantWhenEnabled() { + P2PConfig p2pConfigOverwritten = + P2PConfig.builder().specProvider(spec).executionProofTopicEnabled(true).build(); + filter = new Eth2GossipTopicFilter(recentChainData, SSZ_SNAPPY, spec, p2pConfigOverwritten); + assumeThat(nextSpecMilestone).isEqualTo(ELECTRA); + for (int i = 0; i < Constants.MAX_EXECUTION_PROOF_SUBNETS.intValue(); i++) { + assertThat(filter.isRelevantTopic(getTopicName(getExecutionProofSubnetTopicName(i)))) + .isTrue(); } - - + } private String getTopicName(final GossipTopicName name) { return GossipTopics.getTopic(currentForkDigest, name, SSZ_SNAPPY); From 950147724cebbcd34b99731830d25576d8516226 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 19 Sep 2025 15:47:26 +1000 Subject: [PATCH 74/98] PR Review Signed-off-by: Gabriel Fukushima --- .../validation/ExecutionProofGossipValidator.java | 4 ++-- .../networking/eth2/gossip/forks/GossipForkManager.java | 2 +- .../teku/services/beaconchain/BeaconChainController.java | 6 +++--- .../main/java/tech/pegasys/teku/cli/options/P2POptions.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 0f9511c6c72..8790ae9e6cc 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -43,7 +43,7 @@ public SafeFuture validate( // TODO need to check for other validations done in the prototype and spec if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { - LOG.warn("ExecutionProof subnetId does not match the gossip subnetId"); + LOG.trace("ExecutionProof for block root {} does not match the gossip subnetId", executionProof.getBlockRoot()); return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); } @@ -53,7 +53,7 @@ public SafeFuture validate( } // Validated the execution proof - LOG.debug("Received and validated execution proof for block {}", executionProof.getBlockHash()); + LOG.trace("Received and validated execution proof for block root {}", executionProof.getBlockRoot()); receivedValidExecutionProofSet.add(executionProof); return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java index a7a82acfd12..29cc9fbb168 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkManager.java @@ -193,7 +193,7 @@ public synchronized void publishDataColumnSidecar(final DataColumnSidecar dataCo public void publishExecutionProof(final ExecutionProof executionProof) { // for now we don't have a slot in the message data (execution proof) to use // I believe it's safe to just check the current epoch - LOG.debug("Publishing execution proof for slot {}", executionProof); + // TODO: talk to Kev and see if it makes sense to include the slot in the message UInt64 slot = spec.computeStartSlotAtEpoch(spec.getCurrentEpoch(recentChainData.getStore())); publishMessage( slot, executionProof, "execution proof", GossipForkSubscriptions::publishExecutionProof); 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 5bb9bdef1ac..ca29edfbca2 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 @@ -468,7 +468,7 @@ protected void startServices() { new BlobIdentifier(blobSidecar.getBlockRoot(), blobSidecar.getIndex()))); executionProofManager.subscribeToValidExecutionProofs( (executionProof, remoteOrigin) -> - LOG.info("Received valid execution proof: {}", executionProof)); + LOG.debug("Received valid execution proof: {}", executionProof)); final Optional network = beaconConfig.eth2NetworkConfig().getEth2Network(); if (network.isPresent() && network.get() == Eth2Network.EPHEMERY) { @@ -674,10 +674,10 @@ protected void initExecutionLayer() { protected void initZkChain() { LOG.debug("BeaconChainController.initZkChain()"); - ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); + final ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); // comment for now this will be used in the future // final ExecutionProofGossipChannel executionProofGossipChannel = - eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); + // eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); if (zkConfig.isStatelessValidationEnabled()) { final ExecutionProofGossipValidator executionProofGossipValidator = ExecutionProofGossipValidator.create(); diff --git a/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java b/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java index 62250712e08..529c4ae2654 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java @@ -399,7 +399,7 @@ The network interface(s) on which the node listens for P2P communication. names = {"--Xexecution-proof-topics-enabled"}, paramLabel = "", showDefaultValue = Visibility.ALWAYS, - description = "Add all topic filtering to p2p configuration.", + description = "Enable all execution proof topic filtering to p2p configuration.", arity = "0..1", hidden = true, fallbackValue = "true") From 1327a13aaaea56546f6c0e02b49a8e2261900124 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 19 Sep 2025 15:47:39 +1000 Subject: [PATCH 75/98] spotless Signed-off-by: Gabriel Fukushima --- .../validation/ExecutionProofGossipValidator.java | 7 +++++-- .../teku/services/beaconchain/BeaconChainController.java | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 8790ae9e6cc..d8e001121ca 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -43,7 +43,9 @@ public SafeFuture validate( // TODO need to check for other validations done in the prototype and spec if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { - LOG.trace("ExecutionProof for block root {} does not match the gossip subnetId", executionProof.getBlockRoot()); + LOG.trace( + "ExecutionProof for block root {} does not match the gossip subnetId", + executionProof.getBlockRoot()); return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); } @@ -53,7 +55,8 @@ public SafeFuture validate( } // Validated the execution proof - LOG.trace("Received and validated execution proof for block root {}", executionProof.getBlockRoot()); + LOG.trace( + "Received and validated execution proof for block root {}", executionProof.getBlockRoot()); receivedValidExecutionProofSet.add(executionProof); return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); } 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 ca29edfbca2..696288ee6ac 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 @@ -87,7 +87,6 @@ import tech.pegasys.teku.networking.eth2.gossip.BlobSidecarGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.BlockGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.DataColumnSidecarGossipChannel; -import tech.pegasys.teku.networking.eth2.gossip.ExecutionProofGossipChannel; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSubnetsSubscriber; import tech.pegasys.teku.networking.eth2.gossip.subnets.AllSyncCommitteeSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber; From b981eee7f74e4c8fa752fa57a930b9ad2c01148f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 19 Sep 2025 15:49:48 +1000 Subject: [PATCH 76/98] add TODO Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/services/beaconchain/BeaconChainController.java | 1 + 1 file changed, 1 insertion(+) 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 696288ee6ac..a36e5e0961f 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 @@ -674,6 +674,7 @@ protected void initExecutionLayer() { protected void initZkChain() { LOG.debug("BeaconChainController.initZkChain()"); final ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); + // TODO: We will eventually need the Gossip in the EP Manager for publishing the proofs we produce? // comment for now this will be used in the future // final ExecutionProofGossipChannel executionProofGossipChannel = // eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); From 0ae1e8a02703b8294931c9f830230437c70602e3 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 22 Sep 2025 10:09:09 +1000 Subject: [PATCH 77/98] review part 2 Signed-off-by: Gabriel Fukushima --- .../eth2/gossip/ExecutionProofGossipChannel.java | 6 +++--- .../teku/networking/eth2/Eth2P2PNetworkFactory.java | 11 ++++++----- .../services/beaconchain/BeaconChainController.java | 1 + .../tech/pegasys/teku/cli/options/P2POptions.java | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java index 1ada673e061..a9ea365a9f8 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -21,9 +21,9 @@ public interface ExecutionProofGossipChannel extends VoidReturningChannelInterfa ExecutionProofGossipChannel NOOP = executionProof -> {}; - default void publishExecutionProof(final List executionProofs) { - executionProofs.forEach(this::publishExecutionProof); + default void publishExecutionProofs(final List executionProofs) { + executionProofs.forEach(this::publishExecutionProofs); } - void publishExecutionProof(ExecutionProof executionProof); + void publishExecutionProofs(ExecutionProof executionProof); } diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index d3a1c02c3a0..238f687116f 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -376,7 +376,7 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { .map( forkAndSpecMilestone -> createSubscriptions( - forkAndSpecMilestone, metricsSystem, network, gossipEncoding)) + forkAndSpecMilestone, metricsSystem, network, gossipEncoding, config.isExecutionProofTopicEnabled())) .forEach(gossipForkManagerBuilder::fork); final GossipForkManager gossipForkManager = gossipForkManagerBuilder.build(); @@ -405,7 +405,8 @@ private GossipForkSubscriptions createSubscriptions( final ForkAndSpecMilestone forkAndSpecMilestone, final NoOpMetricsSystem metricsSystem, final DiscoveryNetwork network, - final GossipEncoding gossipEncoding) { + final GossipEncoding gossipEncoding, + final boolean isExecutionProofTopicEnabled) { return switch (forkAndSpecMilestone.getSpecMilestone()) { case PHASE0 -> new GossipForkSubscriptionsPhase0( @@ -519,7 +520,7 @@ private GossipForkSubscriptions createSubscriptions( signedBlsToExecutionChangeProcessor, debugDataDumper, executionProofOperationProcessor, - generateConfig().isExecutionProofTopicEnabled()); + isExecutionProofTopicEnabled); case FULU -> new GossipForkSubscriptionsFulu( forkAndSpecMilestone.getFork(), @@ -543,7 +544,7 @@ private GossipForkSubscriptions createSubscriptions( debugDataDumper, DasGossipLogger.NOOP, executionProofOperationProcessor, - generateConfig().isExecutionProofTopicEnabled()); + isExecutionProofTopicEnabled); case GLOAS -> new GossipForkSubscriptionsGloas( forkAndSpecMilestone.getFork(), @@ -567,7 +568,7 @@ private GossipForkSubscriptions createSubscriptions( debugDataDumper, DasGossipLogger.NOOP, executionProofOperationProcessor, - generateConfig().isExecutionProofTopicEnabled()); + isExecutionProofTopicEnabled); }; } 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 a36e5e0961f..2cb429a591a 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 @@ -467,6 +467,7 @@ protected void startServices() { new BlobIdentifier(blobSidecar.getBlockRoot(), blobSidecar.getIndex()))); executionProofManager.subscribeToValidExecutionProofs( (executionProof, remoteOrigin) -> + // TODO add actual logic to handle valid execution proofs LOG.debug("Received valid execution proof: {}", executionProof)); final Optional network = beaconConfig.eth2NetworkConfig().getEth2Network(); diff --git a/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java b/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java index 529c4ae2654..9a6096e7982 100644 --- a/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java +++ b/teku/src/main/java/tech/pegasys/teku/cli/options/P2POptions.java @@ -399,7 +399,7 @@ The network interface(s) on which the node listens for P2P communication. names = {"--Xexecution-proof-topics-enabled"}, paramLabel = "", showDefaultValue = Visibility.ALWAYS, - description = "Enable all execution proof topic filtering to p2p configuration.", + description = "Enable all execution proof topics", arity = "0..1", hidden = true, fallbackValue = "true") From 16c520aa229525e03cec4b222d1802149a00e0e8 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 22 Sep 2025 10:09:43 +1000 Subject: [PATCH 78/98] spotless Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java | 6 +++++- .../teku/services/beaconchain/BeaconChainController.java | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 238f687116f..a44555bf14a 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -376,7 +376,11 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { .map( forkAndSpecMilestone -> createSubscriptions( - forkAndSpecMilestone, metricsSystem, network, gossipEncoding, config.isExecutionProofTopicEnabled())) + forkAndSpecMilestone, + metricsSystem, + network, + gossipEncoding, + config.isExecutionProofTopicEnabled())) .forEach(gossipForkManagerBuilder::fork); final GossipForkManager gossipForkManager = gossipForkManagerBuilder.build(); 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 2cb429a591a..d58410190f8 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 @@ -675,7 +675,8 @@ protected void initExecutionLayer() { protected void initZkChain() { LOG.debug("BeaconChainController.initZkChain()"); final ZkChainConfiguration zkConfig = beaconConfig.zkChainConfiguration(); - // TODO: We will eventually need the Gossip in the EP Manager for publishing the proofs we produce? + // TODO: We will eventually need the Gossip in the EP Manager for publishing the proofs we + // produce? // comment for now this will be used in the future // final ExecutionProofGossipChannel executionProofGossipChannel = // eventChannels.getPublisher(ExecutionProofGossipChannel.class, networkAsyncRunner); From de2a545cc581c5df5d231a15bb0da11e1876e9ee Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 22:42:00 +1000 Subject: [PATCH 79/98] rename methods of the interface Signed-off-by: Gabriel Fukushima --- .../networking/eth2/gossip/ExecutionProofGossipChannel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java index a9ea365a9f8..15f4b34218f 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipChannel.java @@ -22,8 +22,8 @@ public interface ExecutionProofGossipChannel extends VoidReturningChannelInterfa ExecutionProofGossipChannel NOOP = executionProof -> {}; default void publishExecutionProofs(final List executionProofs) { - executionProofs.forEach(this::publishExecutionProofs); + executionProofs.forEach(this::publishExecutionProof); } - void publishExecutionProofs(ExecutionProof executionProof); + void publishExecutionProof(ExecutionProof executionProof); } From db19aa7e396a9a8a8eaa987828aa6dc6667c6a3f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 22:59:04 +1000 Subject: [PATCH 80/98] spotless Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java | 4 ++-- .../networking/eth2/gossip/forks/GossipForkSubscriptions.java | 2 +- .../gossip/forks/versions/GossipForkSubscriptionsGloas.java | 2 +- .../forks/versions/GossipForkSubscriptionsGloasBpo.java | 2 +- .../pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index fb6eeba8953..7fa193d6502 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -86,8 +86,8 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; @@ -640,7 +640,7 @@ private void validate() { "gossipedSignedBlsToExecutionChangeProcessor", gossipedSignedBlsToExecutionChangeProcessor); assertNotNull( "gossipedDataColumnSidecarOperationProcessor", dataColumnSidecarOperationProcessor); - //TODO maybe add an assertion here for EP Op Processor? + // TODO maybe add an assertion here for EP Op Processor? assertNotNull("gossipedPayloadAttestationMessageProcessor", payloadAttestationMessageProcessor); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index edf40c38bf5..aab2cde0906 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -20,8 +20,8 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java index 8064df58925..51723866b5c 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java @@ -27,8 +27,8 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java index b836988bd3d..69fd6fc6544 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java @@ -24,8 +24,8 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 00c8d79d211..2623c4e6bf4 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -99,8 +99,8 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; From 72a6d58d3168eb5555503e183322d882c6145989 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 23:16:38 +1000 Subject: [PATCH 81/98] fix test Signed-off-by: Gabriel Fukushima --- .../forks/versions/GossipForkSubscriptionsGloasTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasTest.java index 52d5db39423..e5ebf7696e4 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasTest.java @@ -88,6 +88,8 @@ private GossipForkSubscriptionsGloas createGossipForkSubscriptionGloas() { noopOperationProcessor, noopOperationProcessor, DebugDataDumper.NOOP, - DasGossipLogger.NOOP); + DasGossipLogger.NOOP, + noopOperationProcessor, + false); } } From caee24270046b6904e3f8148b0b5e534b302e1ea Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 23:19:12 +1000 Subject: [PATCH 82/98] change log level Signed-off-by: Gabriel Fukushima --- .../networking/eth2/gossip/ExecutionProofGossipManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index 67d393841c1..fbd8484949a 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -61,7 +61,7 @@ public void publish(final ExecutionProof executionProof) { executionProofSubnetSubscriptions .gossip(executionProof) .finish( - __ -> LOG.info(executionProof + " published successfully"), - error -> LOG.info(executionProof + error.getMessage())); + __ -> LOG.trace(executionProof + " published successfully"), + error -> LOG.trace(executionProof + error.getMessage())); } } From 2d65f594739ca5e7786c017a6d2b97ca70a58a9c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 23:23:43 +1000 Subject: [PATCH 83/98] fix size of the set created Signed-off-by: Gabriel Fukushima --- .../validation/ExecutionProofGossipValidator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index d8e001121ca..cd8d52459fc 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -30,7 +30,8 @@ public class ExecutionProofGossipValidator { public static ExecutionProofGossipValidator create() { return new ExecutionProofGossipValidator( - LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue())); + // max subnets * 2 epochs * slots per epoch 32 based on mainnet for now + LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue() * 64)); } public ExecutionProofGossipValidator(final Set receivedValidExecutionProofSet) { From eabcd2a81ea5a6221fd113f41e1f4cc44384f608 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 23:25:07 +1000 Subject: [PATCH 84/98] add block hash to log Signed-off-by: Gabriel Fukushima --- .../validation/ExecutionProofGossipValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index cd8d52459fc..5aea9f5e65c 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -57,7 +57,7 @@ public SafeFuture validate( // Validated the execution proof LOG.trace( - "Received and validated execution proof for block root {}", executionProof.getBlockRoot()); + "Received and validated execution proof for block root {}, block hash {}", executionProof.getBlockRoot(), executionProof.getBlockHash()); receivedValidExecutionProofSet.add(executionProof); return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); } From 818ad31d666a5467e7e00ba7f09d0bdc6e684715 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Sat, 27 Sep 2025 23:25:20 +1000 Subject: [PATCH 85/98] spotless Signed-off-by: Gabriel Fukushima --- .../validation/ExecutionProofGossipValidator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 5aea9f5e65c..acea0a8e47e 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -30,7 +30,7 @@ public class ExecutionProofGossipValidator { public static ExecutionProofGossipValidator create() { return new ExecutionProofGossipValidator( - // max subnets * 2 epochs * slots per epoch 32 based on mainnet for now + // max subnets * 2 epochs * slots per epoch 32 based on mainnet for now LimitedSet.createSynchronized(MAX_EXECUTION_PROOF_SUBNETS.intValue() * 64)); } @@ -57,7 +57,9 @@ public SafeFuture validate( // Validated the execution proof LOG.trace( - "Received and validated execution proof for block root {}, block hash {}", executionProof.getBlockRoot(), executionProof.getBlockHash()); + "Received and validated execution proof for block root {}, block hash {}", + executionProof.getBlockRoot(), + executionProof.getBlockHash()); receivedValidExecutionProofSet.add(executionProof); return SafeFuture.completedFuture(InternalValidationResult.ACCEPT); } From e389e0ff38fd09f919c2c3a3bc52ff33e0892757 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 29 Sep 2025 09:21:28 +1000 Subject: [PATCH 86/98] remove unnecessary comment Signed-off-by: Gabriel Fukushima --- .../executionproofs/ExecutionProofManagerImpl.java | 1 - 1 file changed, 1 deletion(-) 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 4e279617019..4fd3e7cdb95 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 @@ -27,7 +27,6 @@ public class ExecutionProofManagerImpl implements ExecutionProofManager { final ExecutionProofGossipValidator executionProofGossipValidator; - // final ExecutionProofGossipValidator executionProofGossipValidator; private final Subscribers receivedExecutionProofSubscribers = Subscribers.create(true); From 3b92c105ccae7e6644bc63e5e552d73e6224dd42 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 12:04:08 +1000 Subject: [PATCH 87/98] remove changes in PeerSubnetSubscriptions Signed-off-by: Gabriel Fukushima --- .../eth2/Eth2P2PNetworkBuilder.java | 2 - .../subnets/PeerSubnetSubscriptions.java | 65 +++---------------- .../subnets/PeerSubnetSubscriptionsTest.java | 2 - .../eth2/gossip/subnets/SubnetScorerTest.java | 12 ++-- .../eth2/Eth2P2PNetworkFactory.java | 2 - 5 files changed, 13 insertions(+), 70 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 7fa193d6502..39a3b19f241 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -594,8 +594,6 @@ protected DiscoveryNetwork buildNetwork( syncCommitteeSubnetService, dataColumnSidecarSubnetTopicProvider, dataColumnSidecarSubnetService, - executionProofSubnetTopicProvider, - executionProofSubnetService, config.getTargetSubnetSubscriberCount(), subnetPeerCountGauge), reputationManager, diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index baa7d81b785..c360555d0d0 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -47,7 +47,6 @@ public class PeerSubnetSubscriptions { private final SubnetSubscriptions attestationSubnetSubscriptions; private final SubnetSubscriptions syncCommitteeSubnetSubscriptions; private final SubnetSubscriptions dataColumnSidecarSubnetSubscriptions; - private final SubnetSubscriptions executionProofSubnetSubscriptions; private final NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator; private final int targetSubnetSubscriberCount; @@ -56,13 +55,11 @@ private PeerSubnetSubscriptions( final SubnetSubscriptions attestationSubnetSubscriptions, final SubnetSubscriptions syncCommitteeSubnetSubscriptions, final SubnetSubscriptions dataColumnSidecarSubnetSubscriptions, - final SubnetSubscriptions executionProofSubnetSubscriptions, final NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator, final int targetSubnetSubscriberCount) { this.attestationSubnetSubscriptions = attestationSubnetSubscriptions; this.syncCommitteeSubnetSubscriptions = syncCommitteeSubnetSubscriptions; this.dataColumnSidecarSubnetSubscriptions = dataColumnSidecarSubnetSubscriptions; - this.executionProofSubnetSubscriptions = executionProofSubnetSubscriptions; this.nodeIdToDataColumnSidecarSubnetsCalculator = nodeIdToDataColumnSidecarSubnetsCalculator; this.targetSubnetSubscriberCount = targetSubnetSubscriberCount; } @@ -76,8 +73,6 @@ public static PeerSubnetSubscriptions create( final SubnetSubscriptionService syncCommitteeSubnetService, final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider, final SubnetSubscriptionService dataColumnSidecarSubnetService, - final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider, - final SubnetSubscriptionService executionProofSubnetService, final int targetSubnetSubscriberCount, final SettableLabelledGauge subnetPeerCountGauge) { final Map> subscribersByTopic = network.getSubscribersByTopic(); @@ -94,8 +89,7 @@ public static PeerSubnetSubscriptions create( final PeerSubnetSubscriptions subscriptions = builder( currentSchemaDefinitions, - SszBitvectorSchema.create(dataColumnSidecarSubnetCount), - SszBitvectorSchema.create(MAX_EXECUTION_PROOF_SUBNETS.intValue())) + SszBitvectorSchema.create(dataColumnSidecarSubnetCount)) .targetSubnetSubscriberCount(targetSubnetSubscriberCount) .nodeIdToDataColumnSidecarSubnetsCalculator(nodeIdToDataColumnSidecarSubnetsCalculator) .attestationSubnetSubscriptions( @@ -143,20 +137,6 @@ public static PeerSubnetSubscriptions create( Collections.emptySet()) .forEach(subscriber -> b.addSubscriber(columnSubnet, subscriber)); })) - .executionProofSubnetSubscriptions( - b -> - executionProofSubnetService - .getSubnets() - .forEach( - execSubnet -> { - b.addRelevantSubnet(execSubnet); - subscribersByTopic - .getOrDefault( - executionProofSubnetTopicProvider.getTopicForSubnet( - execSubnet), - Collections.emptySet()) - .forEach(subscriber -> b.addSubscriber(execSubnet, subscriber)); - })) .build(); updateMetrics(currentSchemaDefinitions, subnetPeerCountGauge, subscriptions); return subscriptions; @@ -194,23 +174,19 @@ private static IntStream streamAllSyncCommitteeSubnetIds( static Builder builder( final SchemaDefinitionsSupplier currentSchemaDefinitions, - final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, - final SszBitvectorSchema executionProofSubnetSubscription) { + final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { return new Builder( currentSchemaDefinitions, - dataColumnSidecarSubnetBitmaskSchema, - executionProofSubnetSubscription); + dataColumnSidecarSubnetBitmaskSchema); } @VisibleForTesting static PeerSubnetSubscriptions createEmpty( final SchemaDefinitionsSupplier currentSchemaDefinitions, - final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, - final SszBitvectorSchema executionProofSubnetSubscription) { + final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { return builder( currentSchemaDefinitions, - dataColumnSidecarSubnetBitmaskSchema, - executionProofSubnetSubscription) + dataColumnSidecarSubnetBitmaskSchema) .nodeIdToDataColumnSidecarSubnetsCalculator(NodeIdToDataColumnSidecarSubnetsCalculator.NOOP) .build(); } @@ -227,10 +203,6 @@ public int getSubscriberCountForDataColumnSidecarSubnet(final int subnetId) { return dataColumnSidecarSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); } - public int getSubscriberCountForExecutionProofSubnet(final int subnetId) { - return executionProofSubnetSubscriptions.getSubscriberCountForSubnet(subnetId); - } - public SszBitvector getAttestationSubnetSubscriptions(final NodeId peerId) { return attestationSubnetSubscriptions.getSubnetSubscriptions(peerId); } @@ -243,10 +215,6 @@ public SszBitvector getDataColumnSidecarSubnetSubscriptions(final NodeId peerId) return dataColumnSidecarSubnetSubscriptions.getSubnetSubscriptions(peerId); } - public Optional getExecutionProofSubnetSubscriptions(final NodeId peerId) { - return Optional.of(executionProofSubnetSubscriptions.getSubnetSubscriptions(peerId)); - } - public SszBitvector getDataColumnSidecarSubnetSubscriptionsByNodeId( final UInt256 peerId, final Optional custodySubnetCount) { return nodeIdToDataColumnSidecarSubnetsCalculator @@ -266,11 +234,7 @@ public boolean isDataColumnSidecarSubnetRelevant(final int subnetId) { return dataColumnSidecarSubnetSubscriptions.isSubnetRelevant(subnetId); } - public boolean isExecutionProofSubnetRelevant(final int subnetId) { - return executionProofSubnetSubscriptions.isSubnetRelevant(subnetId); - } - - public PeerScorer createScorer() { + public PeerScorer createScorer() { return SubnetScorer.create(this); } @@ -288,8 +252,7 @@ private OptionalInt getMinSubscriberCount() { List.of( attestationSubnetSubscriptions.getMinSubscriberCount(), syncCommitteeSubnetSubscriptions.getMinSubscriberCount(), - dataColumnSidecarSubnetSubscriptions.getMinSubscriberCount(), - executionProofSubnetSubscriptions.getMinSubscriberCount())); + dataColumnSidecarSubnetSubscriptions.getMinSubscriberCount())); } private static OptionalInt optionalMin(final List optionalInts) { @@ -396,22 +359,19 @@ public static class Builder { private final SubnetSubscriptions.Builder attestationSubnetSubscriptions; private final SubnetSubscriptions.Builder syncCommitteeSubnetSubscriptions; private final SubnetSubscriptions.Builder dataColumnSidecarSubnetSubscriptions; - private final SubnetSubscriptions.Builder executionProofSubnetSubscriptions; private NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator; private int targetSubnetSubscriberCount = 2; private Builder( final SchemaDefinitionsSupplier currentSchemaDefinitions, - final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema, - final SszBitvectorSchema executionProofSubnetSubscription) { + final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { attestationSubnetSubscriptions = SubnetSubscriptions.builder(currentSchemaDefinitions.getAttnetsENRFieldSchema()); syncCommitteeSubnetSubscriptions = SubnetSubscriptions.builder(currentSchemaDefinitions.getSyncnetsENRFieldSchema()); dataColumnSidecarSubnetSubscriptions = SubnetSubscriptions.builder(dataColumnSidecarSubnetBitmaskSchema); - executionProofSubnetSubscriptions = - SubnetSubscriptions.builder(executionProofSubnetSubscription); + } public PeerSubnetSubscriptions build() { @@ -419,7 +379,6 @@ public PeerSubnetSubscriptions build() { attestationSubnetSubscriptions.build(), syncCommitteeSubnetSubscriptions.build(), dataColumnSidecarSubnetSubscriptions.build(), - executionProofSubnetSubscriptions.build(), nodeIdToDataColumnSidecarSubnetsCalculator, targetSubnetSubscriberCount); } @@ -451,12 +410,6 @@ public Builder dataColumnSidecarSubnetSubscriptions( return this; } - public Builder executionProofSubnetSubscriptions( - final Consumer consumer) { - consumer.accept(executionProofSubnetSubscriptions); - return this; - } - public Builder nodeIdToDataColumnSidecarSubnetsCalculator( final NodeIdToDataColumnSidecarSubnetsCalculator nodeIdToDataColumnSidecarSubnetsCalculator) { diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java index 71142ad6393..8f645db1d3b 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java @@ -218,8 +218,6 @@ private PeerSubnetSubscriptions createPeerSubnetSubscriptions() { syncnetSubscriptions, dataColumnSidecarSubnetTopicProvider, dataColumnSubscriptions, - executionProofSubnetTopicProvider, - executionProofSubscriptions, TARGET_SUBSCRIBER_COUNT, subnetPeerCountGauge); } diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java index 83861169073..84519925371 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java @@ -53,8 +53,7 @@ void shouldScoreCandidatePeerWithNoSubnetsAsZero() { SubnetScorer.create( PeerSubnetSubscriptions.createEmpty( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), - SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT))); + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT))); assertThat( scorer.scoreCandidatePeer( createDiscoveryPeer( @@ -69,8 +68,7 @@ void shouldScoreExistingPeerWithNoSubnetsAsZero() { SubnetScorer.create( PeerSubnetSubscriptions.createEmpty( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), - SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT))); + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT))); assertThat(scorer.scoreExistingPeer(new MockNodeId(1))).isZero(); } @@ -85,8 +83,7 @@ void shouldScoreExistingPeersOnSubnetsWithFewPeersMoreHighly() { SubnetScorer.create( PeerSubnetSubscriptions.builder( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), - SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT)) + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT)) .attestationSubnetSubscriptions( b -> b.addRelevantSubnet(1) @@ -137,8 +134,7 @@ void shouldScoreCandidatePeersOnSubnetsWithFewPeersMoreHighly() { SubnetScorer.create( PeerSubnetSubscriptions.builder( () -> schemaDefinitions, - SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT), - SszBitvectorSchema.create(EXECUTION_PROOF_SUBNET_COUNT)) + SszBitvectorSchema.create(DATA_COLUMN_SIDECAR_SUBNET_COUNT)) .attestationSubnetSubscriptions( b -> b.addRelevantSubnet(1) diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 2623c4e6bf4..a272d4a8367 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -350,8 +350,6 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { syncCommitteeSubnetService, dataColumnSidecarSubnetTopicProvider, dataColumnSidecarSubnetService, - executionProofSubnetTopicProvider, - executionProofSubnetService, config.getTargetSubnetSubscriberCount(), subnetPeerCountGauge), reputationManager, From 196f27fed037814be5d211ddf856d0c0fa33f3de Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 12:11:06 +1000 Subject: [PATCH 88/98] PR review part 3 Signed-off-by: Gabriel Fukushima --- .../executionproofs/ExecutionProofManagerImpl.java | 6 ++++-- .../validation/ExecutionProofGossipValidator.java | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) 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 4fd3e7cdb95..2887c53e45f 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 @@ -39,12 +39,14 @@ public ExecutionProofManagerImpl( @Override public void onExecutionProofPublish( - final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) {} - + final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) { + LOG.trace("Published execution proof {}", executionProof); + } @Override public SafeFuture onExecutionProofGossip( final ExecutionProof executionProof, final Optional arrivalTimestamp) { LOG.debug("Received execution proof for block {}", executionProof); + //TODO fix this as this needs to obtain subnetId from the topic we received the proof from return executionProofGossipValidator.validate( executionProof, executionProof.getSubnetId().get()); } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index acea0a8e47e..00e6c26f2e3 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -45,12 +45,13 @@ public SafeFuture validate( // TODO need to check for other validations done in the prototype and spec if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { LOG.trace( - "ExecutionProof for block root {} does not match the gossip subnetId", - executionProof.getBlockRoot()); + "ExecutionProof for block root {} / block hash {} does not match the gossip subnetId", + executionProof.getBlockRoot(),executionProof.getBlockHash()); return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); } if (receivedValidExecutionProofSet.contains(executionProof)) { + LOG.trace("Received duplicate execution proof {}", executionProof); // Already seen and valid return SafeFuture.completedFuture(InternalValidationResult.IGNORE); } From 464a82023b745449c409ebf8cae045da079cb378 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 12:11:32 +1000 Subject: [PATCH 89/98] spotless Signed-off-by: Gabriel Fukushima --- .../ExecutionProofManagerImpl.java | 5 +++-- .../ExecutionProofGossipValidator.java | 5 +++-- .../gossip/subnets/PeerSubnetSubscriptions.java | 17 ++++------------- 3 files changed, 10 insertions(+), 17 deletions(-) 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 2887c53e45f..870c3adb221 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 @@ -40,13 +40,14 @@ public ExecutionProofManagerImpl( @Override public void onExecutionProofPublish( final ExecutionProof executionProof, final RemoteOrigin remoteOrigin) { - LOG.trace("Published execution proof {}", executionProof); + LOG.trace("Published execution proof {}", executionProof); } + @Override public SafeFuture onExecutionProofGossip( final ExecutionProof executionProof, final Optional arrivalTimestamp) { LOG.debug("Received execution proof for block {}", executionProof); - //TODO fix this as this needs to obtain subnetId from the topic we received the proof from + // TODO fix this as this needs to obtain subnetId from the topic we received the proof from return executionProofGossipValidator.validate( executionProof, executionProof.getSubnetId().get()); } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 00e6c26f2e3..30a92aa8742 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -46,12 +46,13 @@ public SafeFuture validate( if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { LOG.trace( "ExecutionProof for block root {} / block hash {} does not match the gossip subnetId", - executionProof.getBlockRoot(),executionProof.getBlockHash()); + executionProof.getBlockRoot(), + executionProof.getBlockHash()); return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); } if (receivedValidExecutionProofSet.contains(executionProof)) { - LOG.trace("Received duplicate execution proof {}", executionProof); + LOG.trace("Received duplicate execution proof {}", executionProof); // Already seen and valid return SafeFuture.completedFuture(InternalValidationResult.IGNORE); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java index c360555d0d0..b951ec0cf18 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptions.java @@ -13,8 +13,6 @@ package tech.pegasys.teku.networking.eth2.gossip.subnets; -import static tech.pegasys.teku.spec.config.Constants.MAX_EXECUTION_PROOF_SUBNETS; - import com.google.common.annotations.VisibleForTesting; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; @@ -87,9 +85,7 @@ public static PeerSubnetSubscriptions create( .orElse(1); final PeerSubnetSubscriptions subscriptions = - builder( - currentSchemaDefinitions, - SszBitvectorSchema.create(dataColumnSidecarSubnetCount)) + builder(currentSchemaDefinitions, SszBitvectorSchema.create(dataColumnSidecarSubnetCount)) .targetSubnetSubscriberCount(targetSubnetSubscriberCount) .nodeIdToDataColumnSidecarSubnetsCalculator(nodeIdToDataColumnSidecarSubnetsCalculator) .attestationSubnetSubscriptions( @@ -175,18 +171,14 @@ private static IntStream streamAllSyncCommitteeSubnetIds( static Builder builder( final SchemaDefinitionsSupplier currentSchemaDefinitions, final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { - return new Builder( - currentSchemaDefinitions, - dataColumnSidecarSubnetBitmaskSchema); + return new Builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema); } @VisibleForTesting static PeerSubnetSubscriptions createEmpty( final SchemaDefinitionsSupplier currentSchemaDefinitions, final SszBitvectorSchema dataColumnSidecarSubnetBitmaskSchema) { - return builder( - currentSchemaDefinitions, - dataColumnSidecarSubnetBitmaskSchema) + return builder(currentSchemaDefinitions, dataColumnSidecarSubnetBitmaskSchema) .nodeIdToDataColumnSidecarSubnetsCalculator(NodeIdToDataColumnSidecarSubnetsCalculator.NOOP) .build(); } @@ -234,7 +226,7 @@ public boolean isDataColumnSidecarSubnetRelevant(final int subnetId) { return dataColumnSidecarSubnetSubscriptions.isSubnetRelevant(subnetId); } - public PeerScorer createScorer() { + public PeerScorer createScorer() { return SubnetScorer.create(this); } @@ -371,7 +363,6 @@ private Builder( SubnetSubscriptions.builder(currentSchemaDefinitions.getSyncnetsENRFieldSchema()); dataColumnSidecarSubnetSubscriptions = SubnetSubscriptions.builder(dataColumnSidecarSubnetBitmaskSchema); - } public PeerSubnetSubscriptions build() { From 36e31c51d48a4eed9ea24970eef1bea422d50d6f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 14:06:20 +1000 Subject: [PATCH 90/98] spotless Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java | 4 ---- .../eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java | 2 -- .../pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java | 5 +---- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 39a3b19f241..e020d682198 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -49,7 +49,6 @@ import tech.pegasys.teku.networking.eth2.gossip.forks.versions.GossipForkSubscriptionsPhase0; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetTopicProvider; -import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.NodeIdToDataColumnSidecarSubnetsCalculator; import tech.pegasys.teku.networking.eth2.gossip.subnets.PeerSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubnetTopicProvider; @@ -552,9 +551,6 @@ protected DiscoveryNetwork buildNetwork( final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider = new DataColumnSidecarSubnetTopicProvider( combinedChainDataClient.getRecentChainData(), gossipEncoding); - final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider = - new ExecutionProofSubnetTopicProvider( - combinedChainDataClient.getRecentChainData(), gossipEncoding); final TargetPeerRange targetPeerRange = new TargetPeerRange( diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java index 8f645db1d3b..4955607c39c 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java @@ -62,8 +62,6 @@ class PeerSubnetSubscriptionsTest { mock(SyncCommitteeSubnetTopicProvider.class); private final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider = mock(DataColumnSidecarSubnetTopicProvider.class); - private final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider = - mock(ExecutionProofSubnetTopicProvider.class); private final SubnetSubscriptionService syncnetSubscriptions = new SubnetSubscriptionService(); private final SubnetSubscriptionService dataColumnSubscriptions = new SubnetSubscriptionService(); private final SubnetSubscriptionService executionProofSubscriptions = diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index a272d4a8367..46306c3275f 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -63,7 +63,6 @@ import tech.pegasys.teku.networking.eth2.gossip.forks.versions.GossipForkSubscriptionsPhase0; import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.DataColumnSidecarSubnetTopicProvider; -import tech.pegasys.teku.networking.eth2.gossip.subnets.ExecutionProofSubnetTopicProvider; import tech.pegasys.teku.networking.eth2.gossip.subnets.NodeIdToDataColumnSidecarSubnetsCalculator; import tech.pegasys.teku.networking.eth2.gossip.subnets.PeerSubnetSubscriptions; import tech.pegasys.teku.networking.eth2.gossip.subnets.SyncCommitteeSubnetTopicProvider; @@ -231,9 +230,7 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { final DataColumnSidecarSubnetTopicProvider dataColumnSidecarSubnetTopicProvider = new DataColumnSidecarSubnetTopicProvider( combinedChainDataClient.getRecentChainData(), gossipEncoding); - final ExecutionProofSubnetTopicProvider executionProofSubnetTopicProvider = - new ExecutionProofSubnetTopicProvider( - combinedChainDataClient.getRecentChainData(), gossipEncoding); + if (rpcEncoding == null) { rpcEncoding = From 5d73f963893663047ba1bcc49a333ee4092ff61e Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 14:12:31 +1000 Subject: [PATCH 91/98] remove unused class Signed-off-by: Gabriel Fukushima --- .../ExecutionProofSubnetTopicProvider.java | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java deleted file mode 100644 index 1cebd65dace..00000000000 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/subnets/ExecutionProofSubnetTopicProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Consensys Software Inc., 2025 - * - * 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. - */ - -package tech.pegasys.teku.networking.eth2.gossip.subnets; - -import static tech.pegasys.teku.networking.eth2.gossip.topics.GossipTopics.getExecutionProofSubnetTopic; - -import tech.pegasys.teku.infrastructure.bytes.Bytes4; -import tech.pegasys.teku.networking.eth2.gossip.encoding.GossipEncoding; -import tech.pegasys.teku.storage.client.RecentChainData; - -public class ExecutionProofSubnetTopicProvider { - private final RecentChainData recentChainData; - private final GossipEncoding gossipEncoding; - - public ExecutionProofSubnetTopicProvider( - final RecentChainData recentChainData, final GossipEncoding gossipEncoding) { - this.recentChainData = recentChainData; - this.gossipEncoding = gossipEncoding; - } - - public String getTopicForSubnet(final int subnetId) { - final Bytes4 forkDigest = recentChainData.getCurrentForkDigest().orElseThrow(); - return getExecutionProofSubnetTopic(forkDigest, subnetId, gossipEncoding); - } -} From 59fcf8d890a599c7d398e85b3a3ed89607bd0f39 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 14:12:51 +1000 Subject: [PATCH 92/98] spotless Signed-off-by: Gabriel Fukushima --- .../tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index 46306c3275f..e00e6f188b5 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -231,7 +231,6 @@ protected Eth2P2PNetwork buildNetwork(final P2PConfig config) { new DataColumnSidecarSubnetTopicProvider( combinedChainDataClient.getRecentChainData(), gossipEncoding); - if (rpcEncoding == null) { rpcEncoding = RpcEncoding.createSszSnappyEncoding(spec.getNetworkingConfig().getMaxPayloadSize()); From 244ba6dad88a04087434c22e62a2fe560c32f919 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 14:35:14 +1000 Subject: [PATCH 93/98] remove unused variable Signed-off-by: Gabriel Fukushima --- .../eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java index 4955607c39c..644f4eab9d6 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/PeerSubnetSubscriptionsTest.java @@ -64,8 +64,6 @@ class PeerSubnetSubscriptionsTest { mock(DataColumnSidecarSubnetTopicProvider.class); private final SubnetSubscriptionService syncnetSubscriptions = new SubnetSubscriptionService(); private final SubnetSubscriptionService dataColumnSubscriptions = new SubnetSubscriptionService(); - private final SubnetSubscriptionService executionProofSubscriptions = - new SubnetSubscriptionService(); @BeforeEach public void setUp() { From 19bb1ce7682d2936bf7d1230ea8f68d0cba9ad24 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 30 Sep 2025 15:06:36 +1000 Subject: [PATCH 94/98] remove another unused var Signed-off-by: Gabriel Fukushima --- .../teku/networking/eth2/gossip/subnets/SubnetScorerTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java index 84519925371..6f4307b5f3d 100644 --- a/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java +++ b/networking/eth2/src/test/java/tech/pegasys/teku/networking/eth2/gossip/subnets/SubnetScorerTest.java @@ -45,7 +45,6 @@ class SubnetScorerTest { private final Spec spec = TestSpecFactory.createMinimalAltair(); private final SchemaDefinitions schemaDefinitions = spec.getGenesisSchemaDefinitions(); private static final int DATA_COLUMN_SIDECAR_SUBNET_COUNT = 128; - private static final int EXECUTION_PROOF_SUBNET_COUNT = 8; @Test void shouldScoreCandidatePeerWithNoSubnetsAsZero() { From 71a5d7b73a2f6f0668ff245074919c4760605ad5 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 7 Oct 2025 11:57:30 +1000 Subject: [PATCH 95/98] PR review Signed-off-by: Gabriel Fukushima --- .../executionproofs/ExecutionProofManagerImpl.java | 3 ++- .../validation/ExecutionProofGossipValidator.java | 4 ++-- .../pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java | 6 ++---- .../networking/eth2/gossip/ExecutionProofGossipManager.java | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) 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 870c3adb221..29be05353dc 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 @@ -47,7 +47,8 @@ public void onExecutionProofPublish( public SafeFuture onExecutionProofGossip( final ExecutionProof executionProof, final Optional arrivalTimestamp) { LOG.debug("Received execution proof for block {}", executionProof); - // TODO fix this as this needs to obtain subnetId from the topic we received the proof from + // TODO fix this as this needs to obtain subnetId from the topic we received the proof from? + // this is probably a validation that only makes sense for the stub we're doing return executionProofGossipValidator.validate( executionProof, executionProof.getSubnetId().get()); } diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java index 30a92aa8742..89723ccddc2 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/validation/ExecutionProofGossipValidator.java @@ -43,7 +43,7 @@ public SafeFuture validate( final ExecutionProof executionProof, final UInt64 subnetId) { // TODO need to check for other validations done in the prototype and spec - if (executionProof.getSubnetId().longValue() != subnetId.longValue()) { + if (!executionProof.getSubnetId().get().equals(subnetId)) { LOG.trace( "ExecutionProof for block root {} / block hash {} does not match the gossip subnetId", executionProof.getBlockRoot(), @@ -51,9 +51,9 @@ public SafeFuture validate( return SafeFuture.completedFuture(InternalValidationResult.reject("SubnetId mismatch")); } + // Already seen and valid if (receivedValidExecutionProofSet.contains(executionProof)) { LOG.trace("Received duplicate execution proof {}", executionProof); - // Already seen and valid return SafeFuture.completedFuture(InternalValidationResult.IGNORE); } diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index fd5899d821a..67738bbd247 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -223,8 +223,7 @@ public Eth2P2PNetwork build() { buildNetwork( gossipEncoding, syncCommitteeSubnetService, - dataColumnSidecarSubnetService, - executionProofSubnetService); + dataColumnSidecarSubnetService); final GossipForkManager gossipForkManager = buildGossipForkManager(gossipEncoding, network); @@ -510,8 +509,7 @@ private GossipForkSubscriptions createBpoSubscriptions( protected DiscoveryNetwork buildNetwork( final GossipEncoding gossipEncoding, final SubnetSubscriptionService syncCommitteeSubnetService, - final SubnetSubscriptionService dataColumnSidecarSubnetService, - final SubnetSubscriptionService executionProofSubnetService) { + final SubnetSubscriptionService dataColumnSidecarSubnetService) { final PeerPools peerPools = new PeerPools(); final ReputationManager reputationManager = new DefaultReputationManager( diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index fbd8484949a..79c7578f067 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -61,7 +61,7 @@ public void publish(final ExecutionProof executionProof) { executionProofSubnetSubscriptions .gossip(executionProof) .finish( - __ -> LOG.trace(executionProof + " published successfully"), - error -> LOG.trace(executionProof + error.getMessage())); + __ -> LOG.trace("{} published successfully", executionProof), + error -> LOG.trace("Failed to publish {}, error: {}", executionProof, error.getMessage())); } } From 142c8f31e8f5b6e0f36a747cfce7489609872df9 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 7 Oct 2025 11:57:59 +1000 Subject: [PATCH 96/98] spotless Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java | 5 +---- .../networking/eth2/gossip/ExecutionProofGossipManager.java | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index 67738bbd247..d02cc6860dc 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -220,10 +220,7 @@ public Eth2P2PNetwork build() { final GossipEncoding gossipEncoding = config.getGossipEncoding(); // Build core network and inject eth2 handlers final DiscoveryNetwork network = - buildNetwork( - gossipEncoding, - syncCommitteeSubnetService, - dataColumnSidecarSubnetService); + buildNetwork(gossipEncoding, syncCommitteeSubnetService, dataColumnSidecarSubnetService); final GossipForkManager gossipForkManager = buildGossipForkManager(gossipEncoding, network); diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java index 79c7578f067..92d7cca593b 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/ExecutionProofGossipManager.java @@ -62,6 +62,7 @@ public void publish(final ExecutionProof executionProof) { .gossip(executionProof) .finish( __ -> LOG.trace("{} published successfully", executionProof), - error -> LOG.trace("Failed to publish {}, error: {}", executionProof, error.getMessage())); + error -> + LOG.trace("Failed to publish {}, error: {}", executionProof, error.getMessage())); } } From 738994ccec98fa3c1fafa9c0be96ff19d5b454f0 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 7 Oct 2025 12:01:30 +1000 Subject: [PATCH 97/98] add null validation check on validate() Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index d02cc6860dc..3c2d78890b4 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -629,8 +629,8 @@ private void validate() { "gossipedSignedBlsToExecutionChangeProcessor", gossipedSignedBlsToExecutionChangeProcessor); assertNotNull( "gossipedDataColumnSidecarOperationProcessor", dataColumnSidecarOperationProcessor); - // TODO maybe add an assertion here for EP Op Processor? assertNotNull("gossipedPayloadAttestationMessageProcessor", payloadAttestationMessageProcessor); + assertNotNull("gossipedExecutionProofOperationProcessor", executionProofOperationProcessor); } private void assertNotNull(final String fieldName, final Object fieldValue) { From 837da575f7bba5f72ae07f06bb4d7d5547eb90c2 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 8 Oct 2025 16:29:31 +1000 Subject: [PATCH 98/98] resolve conflicts and merge main into branch Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java | 2 +- .../networking/eth2/gossip/forks/GossipForkSubscriptions.java | 2 +- .../gossip/forks/versions/GossipForkSubscriptionsGloas.java | 4 +--- .../forks/versions/GossipForkSubscriptionsGloasBpo.java | 2 +- .../pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java index a8587362a61..0700f3ad873 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkBuilder.java @@ -86,9 +86,9 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadBid; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java index 3787d2edaf2..42fec34ddca 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/GossipForkSubscriptions.java @@ -21,9 +21,9 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadBid; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java index c02f7024bce..1f9b592b14c 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloas.java @@ -13,8 +13,6 @@ package tech.pegasys.teku.networking.eth2.gossip.forks.versions; -import com.google.common.annotations.VisibleForTesting; -import java.util.Optional; import org.hyperledger.besu.plugin.services.MetricsSystem; import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.bytes.Bytes4; @@ -30,9 +28,9 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadBid; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java index 34cb0d41523..1588bfd8695 100644 --- a/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java +++ b/networking/eth2/src/main/java/tech/pegasys/teku/networking/eth2/gossip/forks/versions/GossipForkSubscriptionsGloasBpo.java @@ -25,9 +25,9 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadBid; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; diff --git a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java index b81cb0ca7c4..89e90eb5267 100644 --- a/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java +++ b/networking/eth2/src/testFixtures/java/tech/pegasys/teku/networking/eth2/Eth2P2PNetworkFactory.java @@ -99,9 +99,9 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.PayloadAttestationMessage; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadBid; import tech.pegasys.teku.spec.datastructures.epbs.versions.gloas.SignedExecutionPayloadEnvelope; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionProof; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing;