diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecMilestone.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecMilestone.java index 301b589b512..a8fc7d72d61 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecMilestone.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecMilestone.java @@ -27,6 +27,7 @@ import tech.pegasys.teku.spec.config.SpecConfigBellatrix; import tech.pegasys.teku.spec.config.SpecConfigCapella; import tech.pegasys.teku.spec.config.SpecConfigDeneb; +import tech.pegasys.teku.spec.config.SpecConfigEip7805; import tech.pegasys.teku.spec.config.SpecConfigElectra; public enum SpecMilestone { @@ -35,7 +36,8 @@ public enum SpecMilestone { BELLATRIX, CAPELLA, DENEB, - ELECTRA; + ELECTRA, + EIP7805; /** * Returns true if this milestone is at or after the supplied milestone ({@code other}) @@ -131,6 +133,7 @@ static Optional getForkVersion( case CAPELLA -> specConfig.toVersionCapella().map(SpecConfigCapella::getCapellaForkVersion); case DENEB -> specConfig.toVersionDeneb().map(SpecConfigDeneb::getDenebForkVersion); case ELECTRA -> specConfig.toVersionElectra().map(SpecConfigElectra::getElectraForkVersion); + case EIP7805 -> specConfig.toVersionEip7805().map(SpecConfigEip7805::getEip7805ForkVersion); }; } @@ -146,6 +149,7 @@ static Optional getForkEpoch(final SpecConfig specConfig, final SpecMile case CAPELLA -> specConfig.toVersionCapella().map(SpecConfigCapella::getCapellaForkEpoch); case DENEB -> specConfig.toVersionDeneb().map(SpecConfigDeneb::getDenebForkEpoch); case ELECTRA -> specConfig.toVersionElectra().map(SpecConfigElectra::getElectraForkEpoch); + case EIP7805 -> specConfig.toVersionEip7805().map(SpecConfigEip7805::getEip7805ForkEpoch); }; } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecVersion.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecVersion.java index 5170facb71e..5a04c6789e6 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecVersion.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/SpecVersion.java @@ -21,6 +21,7 @@ import tech.pegasys.teku.spec.config.SpecConfigBellatrix; import tech.pegasys.teku.spec.config.SpecConfigCapella; import tech.pegasys.teku.spec.config.SpecConfigDeneb; +import tech.pegasys.teku.spec.config.SpecConfigEip7805; import tech.pegasys.teku.spec.config.SpecConfigElectra; import tech.pegasys.teku.spec.logic.DelegatingSpecLogic; import tech.pegasys.teku.spec.logic.SpecLogic; @@ -28,6 +29,7 @@ import tech.pegasys.teku.spec.logic.versions.bellatrix.SpecLogicBellatrix; import tech.pegasys.teku.spec.logic.versions.capella.SpecLogicCapella; import tech.pegasys.teku.spec.logic.versions.deneb.SpecLogicDeneb; +import tech.pegasys.teku.spec.logic.versions.eip7805.SpecLogicEip7805; import tech.pegasys.teku.spec.logic.versions.electra.SpecLogicElectra; import tech.pegasys.teku.spec.logic.versions.phase0.SpecLogicPhase0; import tech.pegasys.teku.spec.schemas.SchemaDefinitions; @@ -35,6 +37,7 @@ import tech.pegasys.teku.spec.schemas.SchemaDefinitionsBellatrix; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsCapella; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip7805; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsPhase0; import tech.pegasys.teku.spec.schemas.registry.SchemaRegistry; @@ -85,6 +88,10 @@ public static Optional create( specConfig .toVersionElectra() .map(specConfigElectra -> createElectra(specConfigElectra, schemaRegistryBuilder)); + case EIP7805 -> + specConfig + .toVersionEip7805() + .map(specConfigEip7732 -> createEip7805(specConfigEip7732, schemaRegistryBuilder)); }; } @@ -149,6 +156,16 @@ static SpecVersion createElectra( return new SpecVersion(SpecMilestone.ELECTRA, specConfig, schemaDefinitions, specLogic); } + static SpecVersion createEip7805( + final SpecConfigEip7805 specConfig, final SchemaRegistryBuilder schemaRegistryBuilder) { + final SchemaRegistry schemaRegistry = + schemaRegistryBuilder.build(SpecMilestone.EIP7805, specConfig); + final SchemaDefinitionsEip7805 schemaDefinitions = new SchemaDefinitionsEip7805(schemaRegistry); + final SpecLogicEip7805 specLogic = + SpecLogicEip7805.create(specConfig, schemaDefinitions, SYSTEM_TIME_PROVIDER); + return new SpecVersion(SpecMilestone.EIP7805, specConfig, schemaDefinitions, specLogic); + } + public SpecMilestone getMilestone() { return milestone; } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfigElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfigElectra.java new file mode 100644 index 00000000000..22cb1a22197 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/DelegatingSpecConfigElectra.java @@ -0,0 +1,118 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.config; + +import java.util.Optional; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; + +public class DelegatingSpecConfigElectra extends DelegatingSpecConfigDeneb + implements SpecConfigElectra { + private final SpecConfigElectra specConfigElectra; + + public DelegatingSpecConfigElectra(final SpecConfigElectra specConfig) { + super(specConfig); + this.specConfigElectra = SpecConfigElectra.required(specConfig); + } + + @Override + public Bytes4 getElectraForkVersion() { + return specConfigElectra.getElectraForkVersion(); + } + + @Override + public UInt64 getElectraForkEpoch() { + return specConfigElectra.getElectraForkEpoch(); + } + + @Override + public UInt64 getMinPerEpochChurnLimitElectra() { + return specConfigElectra.getMinPerEpochChurnLimitElectra(); + } + + @Override + public UInt64 getMinActivationBalance() { + return specConfigElectra.getMinActivationBalance(); + } + + @Override + public UInt64 getMaxEffectiveBalanceElectra() { + return specConfigElectra.getMaxEffectiveBalanceElectra(); + } + + @Override + public int getPendingDepositsLimit() { + return specConfigElectra.getPendingDepositsLimit(); + } + + @Override + public int getPendingPartialWithdrawalsLimit() { + return specConfigElectra.getPendingPartialWithdrawalsLimit(); + } + + @Override + public int getPendingConsolidationsLimit() { + return specConfigElectra.getPendingConsolidationsLimit(); + } + + @Override + public int getMinSlashingPenaltyQuotientElectra() { + return specConfigElectra.getMinSlashingPenaltyQuotientElectra(); + } + + @Override + public int getWhistleblowerRewardQuotientElectra() { + return specConfigElectra.getWhistleblowerRewardQuotientElectra(); + } + + @Override + public int getMaxAttesterSlashingsElectra() { + return specConfigElectra.getMaxAttesterSlashingsElectra(); + } + + @Override + public int getMaxAttestationsElectra() { + return specConfigElectra.getMaxAttestationsElectra(); + } + + @Override + public int getMaxConsolidationRequestsPerPayload() { + return specConfigElectra.getMaxConsolidationRequestsPerPayload(); + } + + @Override + public int getMaxDepositRequestsPerPayload() { + return specConfigElectra.getMaxDepositRequestsPerPayload(); + } + + @Override + public int getMaxWithdrawalRequestsPerPayload() { + return specConfigElectra.getMaxWithdrawalRequestsPerPayload(); + } + + @Override + public int getMaxPendingPartialsPerWithdrawalsSweep() { + return specConfigElectra.getMaxPendingPartialsPerWithdrawalsSweep(); + } + + @Override + public int getMaxPendingDepositsPerEpoch() { + return specConfigElectra.getMaxPendingDepositsPerEpoch(); + } + + @Override + public Optional toVersionElectra() { + return Optional.of(this); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfig.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfig.java index c23b7ceed68..82d3a717f4e 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfig.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfig.java @@ -190,5 +190,9 @@ default Optional toVersionElectra() { return Optional.empty(); } + default Optional toVersionEip7805() { + return Optional.empty(); + } + SpecMilestone getMilestone(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigEip7805.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigEip7805.java new file mode 100644 index 00000000000..f20ad4190ce --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigEip7805.java @@ -0,0 +1,42 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.config; + +import java.util.Optional; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; + +public interface SpecConfigEip7805 extends SpecConfigElectra { + + static SpecConfigEip7805 required(final SpecConfig specConfig) { + return specConfig + .toVersionEip7805() + .orElseThrow( + () -> + new IllegalArgumentException( + "Expected Eip7805 spec config but got: " + + specConfig.getClass().getSimpleName())); + } + + Bytes4 getEip7805ForkVersion(); + + UInt64 getEip7805ForkEpoch(); + + int getIlCommitteeSize(); + + int getMaxTransactionPerInclusionList(); + + @Override + Optional toVersionEip7805(); +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigEip7805Impl.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigEip7805Impl.java new file mode 100644 index 00000000000..789ecaf955b --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigEip7805Impl.java @@ -0,0 +1,98 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.config; + +import java.util.Objects; +import java.util.Optional; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.SpecMilestone; + +public class SpecConfigEip7805Impl extends DelegatingSpecConfigElectra + implements SpecConfigEip7805 { + + private final Bytes4 eip7805ForkVersion; + private final UInt64 eip7805ForkEpoch; + private final int ilCommitteeSize; + private final int maxTransactionPerInclusionList; + + public SpecConfigEip7805Impl( + final SpecConfigElectra specConfig, + final Bytes4 eip7805ForkVersion, + final UInt64 eip7805ForkEpoch, + final int ilCommitteeSize, + final int maxTransactionPerInclusionList) { + super(specConfig); + this.eip7805ForkVersion = eip7805ForkVersion; + this.eip7805ForkEpoch = eip7805ForkEpoch; + this.ilCommitteeSize = ilCommitteeSize; + this.maxTransactionPerInclusionList = maxTransactionPerInclusionList; + } + + @Override + public Bytes4 getEip7805ForkVersion() { + return eip7805ForkVersion; + } + + @Override + public UInt64 getEip7805ForkEpoch() { + return eip7805ForkEpoch; + } + + @Override + public int getIlCommitteeSize() { + return ilCommitteeSize; + } + + @Override + public int getMaxTransactionPerInclusionList() { + return maxTransactionPerInclusionList; + } + + @Override + public Optional toVersionEip7805() { + return Optional.of(this); + } + + @Override + public SpecMilestone getMilestone() { + return SpecMilestone.EIP7805; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final SpecConfigEip7805Impl that = (SpecConfigEip7805Impl) o; + return Objects.equals(specConfig, that.specConfig) + && Objects.equals(eip7805ForkVersion, that.eip7805ForkVersion) + && Objects.equals(eip7805ForkEpoch, that.eip7805ForkEpoch) + && ilCommitteeSize == that.ilCommitteeSize + && maxTransactionPerInclusionList == that.maxTransactionPerInclusionList; + } + + @Override + public int hashCode() { + return Objects.hash( + specConfig, + eip7805ForkVersion, + eip7805ForkEpoch, + ilCommitteeSize, + maxTransactionPerInclusionList); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java index f48941998bd..38bed18c01e 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/SpecConfigReader.java @@ -48,6 +48,7 @@ import tech.pegasys.teku.spec.config.builder.BellatrixBuilder; import tech.pegasys.teku.spec.config.builder.CapellaBuilder; import tech.pegasys.teku.spec.config.builder.DenebBuilder; +import tech.pegasys.teku.spec.config.builder.Eip7805Builder; import tech.pegasys.teku.spec.config.builder.ElectraBuilder; import tech.pegasys.teku.spec.config.builder.SpecConfigBuilder; @@ -208,6 +209,16 @@ public void loadFromMap( unprocessedConfig.remove(constantKey); }); + // Process eip7805 config + streamConfigSetters(Eip7805Builder.class) + .forEach( + setter -> { + final String constantKey = camelToSnakeCase(setter.getName()); + final Object rawValue = unprocessedConfig.get(constantKey); + invokeSetter(setter, configBuilder::eip7805Builder, constantKey, rawValue); + unprocessedConfig.remove(constantKey); + }); + // Check any constants that have been configured and then ignore final Set configuredConstants = Sets.intersection(CONSTANT_KEYS, unprocessedConfig.keySet()); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/Eip7805Builder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/Eip7805Builder.java new file mode 100644 index 00000000000..1c1b5e0a7e0 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/Eip7805Builder.java @@ -0,0 +1,110 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.config.builder; + +import static com.google.common.base.Preconditions.checkNotNull; +import static tech.pegasys.teku.spec.config.SpecConfig.FAR_FUTURE_EPOCH; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import tech.pegasys.teku.infrastructure.bytes.Bytes4; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.config.SpecConfig; +import tech.pegasys.teku.spec.config.SpecConfigAndParent; +import tech.pegasys.teku.spec.config.SpecConfigEip7805; +import tech.pegasys.teku.spec.config.SpecConfigEip7805Impl; +import tech.pegasys.teku.spec.config.SpecConfigElectra; + +public class Eip7805Builder implements ForkConfigBuilder { + + private Bytes4 eip7805ForkVersion; + private UInt64 eip7805ForkEpoch; + + private Integer ilCommitteeSize; + private Integer maxTransactionPerInclusionList; + + Eip7805Builder() {} + + @Override + public SpecConfigAndParent build( + final SpecConfigAndParent specConfigAndParent) { + return SpecConfigAndParent.of( + new SpecConfigEip7805Impl( + specConfigAndParent.specConfig(), + eip7805ForkVersion, + eip7805ForkEpoch, + ilCommitteeSize, + maxTransactionPerInclusionList), + specConfigAndParent); + } + + public Eip7805Builder eip7805ForkEpoch(final UInt64 eip7805ForkEpoch) { + checkNotNull(eip7805ForkEpoch); + this.eip7805ForkEpoch = eip7805ForkEpoch; + return this; + } + + public Eip7805Builder eip7805ForkVersion(final Bytes4 eip7805ForkVersion) { + checkNotNull(eip7805ForkVersion); + this.eip7805ForkVersion = eip7805ForkVersion; + return this; + } + + public Eip7805Builder ilCommitteeSize(final Integer ilCommitteeSize) { + checkNotNull(ilCommitteeSize); + this.ilCommitteeSize = ilCommitteeSize; + return this; + } + + public Eip7805Builder maxTransactionPerInclusionList( + final Integer maxTransactionPerInclusionList) { + checkNotNull(maxTransactionPerInclusionList); + this.maxTransactionPerInclusionList = maxTransactionPerInclusionList; + return this; + } + + @Override + public void validate() { + if (eip7805ForkEpoch == null) { + eip7805ForkEpoch = SpecConfig.FAR_FUTURE_EPOCH; + eip7805ForkVersion = SpecBuilderUtil.PLACEHOLDER_FORK_VERSION; + } + + // Fill default zeros if fork is unsupported + if (eip7805ForkEpoch.equals(FAR_FUTURE_EPOCH)) { + SpecBuilderUtil.fillMissingValuesWithZeros(this); + } + + validateConstants(); + } + + @Override + public Map getValidationMap() { + final Map constants = new HashMap<>(); + + constants.put("eip7805ForkEpoch", eip7805ForkEpoch); + constants.put("eip7805ForkVersion", eip7805ForkVersion); + constants.put("ptcSize", ilCommitteeSize); + constants.put("maxPayloadAttestations", maxTransactionPerInclusionList); + ; + + return constants; + } + + @Override + public void addOverridableItemsToRawConfig(final BiConsumer rawConfig) { + rawConfig.accept("EIP7805_FORK_EPOCH", eip7805ForkEpoch); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java index 5e48e29614c..b06c88058ef 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/config/builder/SpecConfigBuilder.java @@ -742,4 +742,9 @@ public SpecConfigBuilder electraBuilder(final Consumer consumer) builderChain.withBuilder(ElectraBuilder.class, consumer); return this; } + + public SpecConfigBuilder eip7805Builder(final Consumer consumer) { + builderChain.withBuilder(Eip7805Builder.class, consumer); + return this; + } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/Domain.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/Domain.java index 28c40afc6e5..c36432a088f 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/Domain.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/constants/Domain.java @@ -33,4 +33,7 @@ public class Domain { // Capella public static final Bytes4 DOMAIN_BLS_TO_EXECUTION_CHANGE = Bytes4.fromHexString("0x0A000000"); + + // EIP-7805 + public static final Bytes4 DOMAIN_IL_COMMITTEE = Bytes4.fromHexString("0x0C000000"); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/eip7805/SpecLogicEip7805.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/eip7805/SpecLogicEip7805.java new file mode 100644 index 00000000000..ccca42d6201 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/eip7805/SpecLogicEip7805.java @@ -0,0 +1,228 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.logic.versions.eip7805; + +import tech.pegasys.teku.infrastructure.time.TimeProvider; +import tech.pegasys.teku.spec.config.SpecConfigEip7805; +import tech.pegasys.teku.spec.config.SpecConfigEip7805; +import tech.pegasys.teku.spec.config.SpecConfigElectra; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsDataCodec; +import tech.pegasys.teku.spec.logic.common.AbstractSpecLogic; +import tech.pegasys.teku.spec.logic.common.helpers.Predicates; +import tech.pegasys.teku.spec.logic.common.operations.OperationSignatureVerifier; +import tech.pegasys.teku.spec.logic.common.operations.validation.AttestationDataValidator; +import tech.pegasys.teku.spec.logic.common.operations.validation.OperationValidator; +import tech.pegasys.teku.spec.logic.common.util.AttestationUtil; +import tech.pegasys.teku.spec.logic.common.util.BeaconStateUtil; +import tech.pegasys.teku.spec.logic.common.util.BlindBlockUtil; +import tech.pegasys.teku.spec.logic.common.util.BlockProposalUtil; +import tech.pegasys.teku.spec.logic.common.util.ForkChoiceUtil; +import tech.pegasys.teku.spec.logic.common.util.LightClientUtil; +import tech.pegasys.teku.spec.logic.common.util.SyncCommitteeUtil; +import tech.pegasys.teku.spec.logic.common.util.ValidatorsUtil; +import tech.pegasys.teku.spec.logic.versions.altair.statetransition.epoch.ValidatorStatusFactoryAltair; +import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BeaconStateMutatorsBellatrix; +import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BellatrixTransitionHelpers; +import tech.pegasys.teku.spec.logic.versions.bellatrix.util.BlindBlockUtilBellatrix; +import tech.pegasys.teku.spec.logic.versions.capella.operations.validation.OperationValidatorCapella; +import tech.pegasys.teku.spec.logic.versions.deneb.helpers.MiscHelpersDeneb; +import tech.pegasys.teku.spec.logic.versions.deneb.util.ForkChoiceUtilDeneb; +import tech.pegasys.teku.spec.logic.versions.electra.block.BlockProcessorElectra; +import tech.pegasys.teku.spec.logic.versions.electra.forktransition.ElectraStateUpgrade; +import tech.pegasys.teku.spec.logic.versions.electra.helpers.BeaconStateAccessorsElectra; +import tech.pegasys.teku.spec.logic.versions.electra.helpers.BeaconStateMutatorsElectra; +import tech.pegasys.teku.spec.logic.versions.electra.helpers.MiscHelpersElectra; +import tech.pegasys.teku.spec.logic.versions.electra.helpers.PredicatesElectra; +import tech.pegasys.teku.spec.logic.versions.electra.operations.validation.AttestationDataValidatorElectra; +import tech.pegasys.teku.spec.logic.versions.electra.operations.validation.VoluntaryExitValidatorElectra; +import tech.pegasys.teku.spec.logic.versions.electra.statetransition.epoch.EpochProcessorElectra; +import tech.pegasys.teku.spec.logic.versions.electra.util.AttestationUtilElectra; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip7805; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip7805; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; + +import java.util.Optional; + +public class SpecLogicEip7805 extends AbstractSpecLogic { + private final Optional syncCommitteeUtil; + private final Optional lightClientUtil; + + private SpecLogicEip7805( + final Predicates predicates, + final MiscHelpersDeneb miscHelpers, + final BeaconStateAccessorsElectra beaconStateAccessors, + final BeaconStateMutatorsBellatrix beaconStateMutators, + final OperationSignatureVerifier operationSignatureVerifier, + final ValidatorsUtil validatorsUtil, + final BeaconStateUtil beaconStateUtil, + final AttestationUtil attestationUtil, + final OperationValidator operationValidator, + final ValidatorStatusFactoryAltair validatorStatusFactory, + final EpochProcessorElectra epochProcessor, + final BlockProcessorElectra blockProcessor, + final ForkChoiceUtil forkChoiceUtil, + final BlockProposalUtil blockProposalUtil, + final BlindBlockUtil blindBlockUtil, + final SyncCommitteeUtil syncCommitteeUtil, + final LightClientUtil lightClientUtil, + final ElectraStateUpgrade stateUpgrade) { + super( + predicates, + miscHelpers, + beaconStateAccessors, + beaconStateMutators, + operationSignatureVerifier, + validatorsUtil, + beaconStateUtil, + attestationUtil, + operationValidator, + validatorStatusFactory, + epochProcessor, + blockProcessor, + forkChoiceUtil, + blockProposalUtil, + Optional.of(blindBlockUtil), + Optional.of(stateUpgrade)); + this.syncCommitteeUtil = Optional.of(syncCommitteeUtil); + this.lightClientUtil = Optional.of(lightClientUtil); + } + + public static SpecLogicEip7805 create( + final SpecConfigElectra config, + final SchemaDefinitionsElectra schemaDefinitions, + final TimeProvider timeProvider) { + // Helpers + final PredicatesElectra predicates = new PredicatesElectra(config); + final MiscHelpersElectra miscHelpers = + new MiscHelpersElectra(config, predicates, schemaDefinitions); + final BeaconStateAccessorsElectra beaconStateAccessors = + new BeaconStateAccessorsElectra(config, predicates, miscHelpers); + final BeaconStateMutatorsElectra beaconStateMutators = + new BeaconStateMutatorsElectra( + config, miscHelpers, beaconStateAccessors, schemaDefinitions); + + // Operation validation + final OperationSignatureVerifier operationSignatureVerifier = + new OperationSignatureVerifier(miscHelpers, beaconStateAccessors); + + // Util + final ValidatorsUtil validatorsUtil = + new ValidatorsUtil(config, miscHelpers, beaconStateAccessors); + final BeaconStateUtil beaconStateUtil = + new BeaconStateUtil( + config, schemaDefinitions, predicates, miscHelpers, beaconStateAccessors); + final AttestationUtil attestationUtil = + new AttestationUtilElectra(config, schemaDefinitions, beaconStateAccessors, miscHelpers); + final AttestationDataValidator attestationDataValidator = + new AttestationDataValidatorElectra(config, miscHelpers, beaconStateAccessors); + final VoluntaryExitValidatorElectra voluntaryExitValidatorElectra = + new VoluntaryExitValidatorElectra(config, predicates, beaconStateAccessors); + final OperationValidator operationValidator = + new OperationValidatorCapella( + predicates, + beaconStateAccessors, + attestationDataValidator, + attestationUtil, + voluntaryExitValidatorElectra); + final ValidatorStatusFactoryAltair validatorStatusFactory = + new ValidatorStatusFactoryAltair( + config, + beaconStateUtil, + attestationUtil, + predicates, + miscHelpers, + beaconStateAccessors); + final EpochProcessorElectra epochProcessor = + new EpochProcessorElectra( + config, + miscHelpers, + beaconStateAccessors, + beaconStateMutators, + validatorsUtil, + beaconStateUtil, + validatorStatusFactory, + schemaDefinitions, + timeProvider); + final SyncCommitteeUtil syncCommitteeUtil = + new SyncCommitteeUtil( + beaconStateAccessors, validatorsUtil, config, miscHelpers, schemaDefinitions); + final LightClientUtil lightClientUtil = + new LightClientUtil(beaconStateAccessors, syncCommitteeUtil, schemaDefinitions); + final ExecutionRequestsDataCodec executionRequestsDataCodec = + new ExecutionRequestsDataCodec(schemaDefinitions.getExecutionRequestsSchema()); + final BlockProcessorElectra blockProcessor = + new BlockProcessorElectra( + config, + predicates, + miscHelpers, + syncCommitteeUtil, + beaconStateAccessors, + beaconStateMutators, + operationSignatureVerifier, + beaconStateUtil, + attestationUtil, + validatorsUtil, + operationValidator, + schemaDefinitions, + executionRequestsDataCodec); + final ForkChoiceUtil forkChoiceUtil = + new ForkChoiceUtilDeneb( + config, beaconStateAccessors, epochProcessor, attestationUtil, miscHelpers); + final BlockProposalUtil blockProposalUtil = + new BlockProposalUtil(schemaDefinitions, blockProcessor); + + final BlindBlockUtilBellatrix blindBlockUtil = new BlindBlockUtilBellatrix(schemaDefinitions); + + // State upgrade + final ElectraStateUpgrade stateUpgrade = + new ElectraStateUpgrade( + config, schemaDefinitions, beaconStateAccessors, beaconStateMutators); + + return new SpecLogicEip7805( + predicates, + miscHelpers, + beaconStateAccessors, + beaconStateMutators, + operationSignatureVerifier, + validatorsUtil, + beaconStateUtil, + attestationUtil, + operationValidator, + validatorStatusFactory, + epochProcessor, + blockProcessor, + forkChoiceUtil, + blockProposalUtil, + blindBlockUtil, + syncCommitteeUtil, + lightClientUtil, + stateUpgrade); + } + + @Override + public Optional getSyncCommitteeUtil() { + return syncCommitteeUtil; + } + + @Override + public Optional getLightClientUtil() { + return lightClientUtil; + } + + @Override + public Optional getBellatrixTransitionHelpers() { + return Optional.empty(); + } + +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitions.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitions.java index 58509463de8..90025dc6fac 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitions.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitions.java @@ -116,6 +116,11 @@ default Optional toVersionElectra() { return Optional.empty(); } + @NonSchema + default Optional toVersionEip7805() { + return Optional.empty(); + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface NonSchema {} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7805.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7805.java new file mode 100644 index 00000000000..207c57a4d2c --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7805.java @@ -0,0 +1,40 @@ +/* + * Copyright Consensys Software Inc., 2024 + * + * 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.schemas; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Optional; +import tech.pegasys.teku.spec.schemas.registry.SchemaRegistry; + +public class SchemaDefinitionsEip7805 extends SchemaDefinitionsElectra { + + public SchemaDefinitionsEip7805(final SchemaRegistry schemaRegistry) { + super(schemaRegistry); + } + + public static SchemaDefinitionsEip7805 required(final SchemaDefinitions schemaDefinitions) { + checkArgument( + schemaDefinitions instanceof SchemaDefinitionsEip7805, + "Expected definitions of type %s but got %s", + SchemaDefinitionsEip7805.class, + schemaDefinitions.getClass()); + return (SchemaDefinitionsEip7805) schemaDefinitions; + } + + @Override + public Optional toVersionEip7805() { + return Optional.of(this); + } +} diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/gnosis/eip7805.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/gnosis/eip7805.yaml new file mode 100644 index 00000000000..571b7c343a2 --- /dev/null +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/gnosis/eip7805.yaml @@ -0,0 +1,9 @@ +# Mainnet preset - EIP7805 +# Inclusion List Committee +# --------------------------------------------------------------- +# 2**4 (= 16) +IL_COMMITTEE_SIZE: 16 + +# Execution +# --------------------------------------------------------------- +MAX_TRANSACTIONS_PER_INCLUSION_LIST: 1 diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/mainnet/eip7805.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/mainnet/eip7805.yaml new file mode 100644 index 00000000000..571b7c343a2 --- /dev/null +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/mainnet/eip7805.yaml @@ -0,0 +1,9 @@ +# Mainnet preset - EIP7805 +# Inclusion List Committee +# --------------------------------------------------------------- +# 2**4 (= 16) +IL_COMMITTEE_SIZE: 16 + +# Execution +# --------------------------------------------------------------- +MAX_TRANSACTIONS_PER_INCLUSION_LIST: 1 diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/minimal/eip7805.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/minimal/eip7805.yaml new file mode 100644 index 00000000000..571b7c343a2 --- /dev/null +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/minimal/eip7805.yaml @@ -0,0 +1,9 @@ +# Mainnet preset - EIP7805 +# Inclusion List Committee +# --------------------------------------------------------------- +# 2**4 (= 16) +IL_COMMITTEE_SIZE: 16 + +# Execution +# --------------------------------------------------------------- +MAX_TRANSACTIONS_PER_INCLUSION_LIST: 1 diff --git a/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/swift/eip7805.yaml b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/swift/eip7805.yaml new file mode 100644 index 00000000000..571b7c343a2 --- /dev/null +++ b/ethereum/spec/src/main/resources/tech/pegasys/teku/spec/config/presets/swift/eip7805.yaml @@ -0,0 +1,9 @@ +# Mainnet preset - EIP7805 +# Inclusion List Committee +# --------------------------------------------------------------- +# 2**4 (= 16) +IL_COMMITTEE_SIZE: 16 + +# Execution +# --------------------------------------------------------------- +MAX_TRANSACTIONS_PER_INCLUSION_LIST: 1 diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/config/SpecConfigBuilderTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/config/SpecConfigBuilderTest.java index da2f057932e..48ca6b273e6 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/config/SpecConfigBuilderTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/config/SpecConfigBuilderTest.java @@ -33,6 +33,7 @@ import tech.pegasys.teku.spec.config.builder.BellatrixBuilder; import tech.pegasys.teku.spec.config.builder.CapellaBuilder; import tech.pegasys.teku.spec.config.builder.DenebBuilder; +import tech.pegasys.teku.spec.config.builder.Eip7805Builder; import tech.pegasys.teku.spec.config.builder.ElectraBuilder; import tech.pegasys.teku.spec.config.builder.SpecConfigBuilder; import tech.pegasys.teku.spec.datastructures.util.ForkAndSpecMilestone; @@ -49,7 +50,8 @@ class SpecConfigBuilderTest { BellatrixBuilder.class, CapellaBuilder.class, DenebBuilder.class, - ElectraBuilder.class); + ElectraBuilder.class, + Eip7805Builder.class); /** * Ensures Builders have actually non-primitive setters, because primitive setters are silently