From 27ad1ac4b88c9aa29ffacdaba275e4b4e72258c7 Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Fri, 22 Sep 2023 19:46:30 +0800 Subject: [PATCH] Support Deneb fork choice reference tests --- .../teku/reference/Eth2ReferenceTestCase.java | 6 - .../forkchoice/ForkChoiceTestExecutor.java | 54 +++++-- .../forkchoice/StubBlobSidecarManager.java | 139 ++++++++++++++++++ .../teku/ethtests/finder/TestDefinition.java | 26 +++- .../java/tech/pegasys/teku/spec/Spec.java | 11 ++ .../logic/common/helpers/MiscHelpers.java | 12 +- .../deneb/helpers/MiscHelpersDeneb.java | 15 ++ .../spec/schemas/SchemaDefinitionsDeneb.java | 9 ++ .../pegasys/teku/spec/TestSpecFactory.java | 104 +++++-------- 9 files changed, 288 insertions(+), 88 deletions(-) create mode 100644 eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/StubBlobSidecarManager.java diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/Eth2ReferenceTestCase.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/Eth2ReferenceTestCase.java index 224dc435eff..d64220f8158 100644 --- a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/Eth2ReferenceTestCase.java +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/Eth2ReferenceTestCase.java @@ -104,12 +104,6 @@ private TestExecutor getExecutorFor(final TestDefinition testDefinition) { testExecutor = COMMON_TEST_TYPES.get(testDefinition.getTestType()); } - // TODO: https://github.com/Consensys/teku/issues/7539 - if (testDefinition.getFork().equals(TestFork.DENEB) - && testExecutor instanceof ForkChoiceTestExecutor) { - testExecutor = TestExecutor.IGNORE_TESTS; - } - if (testExecutor == null) { return Assertions.fail("Unsupported test type " + testDefinition.getTestType()); } diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java index a5eaa610384..bc130a99094 100644 --- a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/ForkChoiceTestExecutor.java @@ -41,10 +41,12 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.async.eventthread.InlineEventThread; import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.kzg.KZGProof; import tech.pegasys.teku.reference.TestDataUtils; import tech.pegasys.teku.reference.TestExecutor; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState; @@ -61,7 +63,6 @@ import tech.pegasys.teku.spec.executionlayer.ExecutionPayloadStatus; import tech.pegasys.teku.spec.executionlayer.PayloadStatus; import tech.pegasys.teku.spec.logic.common.statetransition.results.BlockImportResult; -import tech.pegasys.teku.statetransition.blobs.BlobSidecarManager; import tech.pegasys.teku.statetransition.forkchoice.ForkChoice; import tech.pegasys.teku.statetransition.forkchoice.ForkChoiceStateProvider; import tech.pegasys.teku.statetransition.forkchoice.MergeTransitionBlockValidator; @@ -76,6 +77,7 @@ public class ForkChoiceTestExecutor implements TestExecutor { private static final Logger LOG = LogManager.getLogger(); + private static final String SSZ_SNAPPY_EXTENSION = ".ssz_snappy"; public static final ImmutableMap FORK_CHOICE_TEST_TYPES = ImmutableMap.builder() .put("fork_choice/get_head", new ForkChoiceTestExecutor()) @@ -103,7 +105,7 @@ public void runTest(final TestDefinition testDefinition) throws Throwable { // Note: The fork choice spec says there may be settings in a meta.yaml file but currently no // tests actually have one, so we currently don't bother trying to load it. final BeaconState anchorState = - TestDataUtils.loadStateFromSsz(testDefinition, "anchor_state.ssz_snappy"); + TestDataUtils.loadStateFromSsz(testDefinition, "anchor_state" + SSZ_SNAPPY_EXTENSION); final Spec spec = testDefinition.getSpec(); final SignedBeaconBlock anchorBlock = loadAnchorBlock(testDefinition); @@ -118,12 +120,13 @@ spec, new SignedBlockAndState(anchorBlock, anchorState)), final MergeTransitionBlockValidator transitionBlockValidator = new MergeTransitionBlockValidator(spec, recentChainData, ExecutionLayerChannel.NOOP); final InlineEventThread eventThread = new InlineEventThread(); + final StubBlobSidecarManager blobSidecarManager = new StubBlobSidecarManager(spec); final ForkChoice forkChoice = new ForkChoice( spec, eventThread, recentChainData, - BlobSidecarManager.NOOP, + blobSidecarManager, new StubForkChoiceNotifier(), new ForkChoiceStateProvider(eventThread, recentChainData), new TickProcessor(spec, recentChainData), @@ -135,7 +138,8 @@ spec, new SignedBlockAndState(anchorBlock, anchorState)), new ExecutionLayerChannelStub(spec, false, Optional.empty()); try { - runSteps(testDefinition, spec, recentChainData, forkChoice, executionLayer); + runSteps( + testDefinition, spec, recentChainData, blobSidecarManager, forkChoice, executionLayer); } catch (final AssertionError e) { final String protoArrayData = recentChainData.getForkChoiceStrategy().orElseThrow().getBlockData().stream() @@ -165,7 +169,7 @@ private SignedBeaconBlock loadAnchorBlock(final TestDefinition testDefinition) { final BeaconBlock anchorBlock = TestDataUtils.loadSsz( testDefinition, - "anchor_block.ssz_snappy", + "anchor_block" + SSZ_SNAPPY_EXTENSION, testDefinition.getSpec()::deserializeBeaconBlock); return SignedBeaconBlock.create(testDefinition.getSpec(), anchorBlock, BLSSignature.empty()); } @@ -174,6 +178,7 @@ private void runSteps( final TestDefinition testDefinition, final Spec spec, final RecentChainData recentChainData, + final StubBlobSidecarManager blobSidecarManager, final ForkChoice forkChoice, final ExecutionLayerChannelStub executionLayer) throws IOException { @@ -188,7 +193,14 @@ private void runSteps( final UInt64 currentSlot = recentChainData.getCurrentSlot().orElse(UInt64.ZERO); LOG.info("Current slot: {} Epoch: {}", currentSlot, spec.computeEpochAtSlot(currentSlot)); } else if (step.containsKey("block")) { - applyBlock(testDefinition, spec, recentChainData, forkChoice, step, executionLayer); + applyBlock( + testDefinition, + spec, + recentChainData, + blobSidecarManager, + forkChoice, + step, + executionLayer); } else if (step.containsKey("attestation")) { applyAttestation(testDefinition, forkChoice, step); @@ -214,7 +226,7 @@ private void applyPowBlock( final ExecutionLayerChannelStub executionLayer) { final String filename = (String) step.get("pow_block"); final PowBlock block = - TestDataUtils.loadSsz(testDefinition, filename + ".ssz_snappy", this::parsePowBlock); + TestDataUtils.loadSsz(testDefinition, filename + SSZ_SNAPPY_EXTENSION, this::parsePowBlock); executionLayer.addPowBlock(block); } @@ -262,7 +274,7 @@ private void applyAttestation( final Attestation attestation = TestDataUtils.loadSsz( testDefinition, - attestationName + ".ssz_snappy", + attestationName + SSZ_SNAPPY_EXTENSION, testDefinition.getSpec().getGenesisSchemaDefinitions().getAttestationSchema()); final Spec spec = testDefinition.getSpec(); assertThat(forkChoice.onAttestation(ValidatableAttestation.from(spec, attestation))) @@ -277,7 +289,7 @@ private void applyAttesterSlashing( final AttesterSlashing attesterSlashing = TestDataUtils.loadSsz( testDefinition, - slashingName + ".ssz_snappy", + slashingName + SSZ_SNAPPY_EXTENSION, testDefinition.getSpec().getGenesisSchemaDefinitions().getAttesterSlashingSchema()); assertDoesNotThrow( () -> @@ -288,6 +300,7 @@ private void applyBlock( final TestDefinition testDefinition, final Spec spec, final RecentChainData recentChainData, + final StubBlobSidecarManager blobSidecarManager, final ForkChoice forkChoice, final Map step, final ExecutionLayerChannelStub executionLayer) { @@ -295,7 +308,28 @@ private void applyBlock( final boolean valid = !step.containsKey("valid") || (boolean) step.get("valid"); final SignedBeaconBlock block = TestDataUtils.loadSsz( - testDefinition, blockName + ".ssz_snappy", spec::deserializeSignedBeaconBlock); + testDefinition, blockName + SSZ_SNAPPY_EXTENSION, spec::deserializeSignedBeaconBlock); + getOptionally(step, "blobs") + .ifPresent( + blobsName -> { + final List blobs = + TestDataUtils.loadSsz( + testDefinition, + blobsName + SSZ_SNAPPY_EXTENSION, + sszBytes -> spec.deserializeBlobsInBlock(sszBytes, block.getSlot())) + .asList(); + @SuppressWarnings("unchecked") + final List proofs = + ((List) get(step, "proofs")) + .stream().map(KZGProof::fromHexString).toList(); + LOG.info( + "Preparing {} blobs with proofs {} for block {}", + blobs.size(), + proofs, + block.getRoot()); + blobSidecarManager.prepareBlobsAndProofsForBlock(block, blobs, proofs); + }); + LOG.info( "Importing block {} at slot {} with parent {}", block.getRoot(), diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/StubBlobSidecarManager.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/StubBlobSidecarManager.java new file mode 100644 index 00000000000..c123fb3c294 --- /dev/null +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/phase0/forkchoice/StubBlobSidecarManager.java @@ -0,0 +1,139 @@ +/* + * 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.reference.phase0.forkchoice; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.kzg.KZGCommitment; +import tech.pegasys.teku.kzg.KZGProof; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.SignedBlobSidecar; +import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.deneb.BeaconBlockBodyDeneb; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; +import tech.pegasys.teku.spec.logic.common.helpers.MiscHelpers; +import tech.pegasys.teku.spec.logic.versions.deneb.blobs.BlobSidecarsAndValidationResult; +import tech.pegasys.teku.spec.logic.versions.deneb.blobs.BlobSidecarsAvailabilityChecker; +import tech.pegasys.teku.statetransition.blobs.BlobSidecarManager; +import tech.pegasys.teku.statetransition.blobs.BlobSidecarManagerImpl; +import tech.pegasys.teku.statetransition.validation.InternalValidationResult; + +/** Simplified version of {@link BlobSidecarManagerImpl} which is used in reference tests */ +class StubBlobSidecarManager implements BlobSidecarManager { + + private final Map blobsAndProofsByBlockRoot = new HashMap<>(); + + private final Spec spec; + + StubBlobSidecarManager(final Spec spec) { + this.spec = spec; + } + + /** Manually provide blobs and proofs for a block * */ + public void prepareBlobsAndProofsForBlock( + final SignedBeaconBlock block, final List blobs, final List proofs) { + blobsAndProofsByBlockRoot.put(block.getRoot(), new BlobsAndProofs(blobs, proofs)); + } + + @Override + public SafeFuture validateAndPrepareForBlockImport( + final SignedBlobSidecar signedBlobSidecar) { + return SafeFuture.failedFuture( + new UnsupportedOperationException("Not available in fork_choice reference tests")); + } + + @Override + public void prepareForBlockImport(final BlobSidecar blobSidecar) { + // NOOP + } + + @Override + public void subscribeToReceivedBlobSidecar( + final ReceivedBlobSidecarListener receivedBlobSidecarListener) { + // NOOP + } + + @Override + public boolean isAvailabilityRequiredAtSlot(final UInt64 slot) { + // NOOP + return false; + } + + /** + * Creates an implementation of {@link BlobSidecarsAvailabilityChecker} which uses the simplified + * {@link MiscHelpers#isDataAvailable(List, List, List)} method with the already provided blobs + * and proofs by the reference test + */ + @Override + public BlobSidecarsAvailabilityChecker createAvailabilityChecker(final SignedBeaconBlock block) { + return new BlobSidecarsAvailabilityChecker() { + @Override + public boolean initiateDataAvailabilityCheck() { + return true; + } + + @Override + public SafeFuture getAvailabilityCheckResult() { + final BlobsAndProofs blobsAndProofs = blobsAndProofsByBlockRoot.get(block.getRoot()); + if (blobsAndProofs == null) { + return SafeFuture.completedFuture(BlobSidecarsAndValidationResult.NOT_REQUIRED); + } + return SafeFuture.completedFuture(validateBatch(block, blobsAndProofs)); + } + + @Override + public BlobSidecarsAndValidationResult validateImmediately( + final List blobSidecars) { + throw new UnsupportedOperationException("Not available in fork_choice reference tests"); + } + + public BlobSidecarsAndValidationResult validateBatch( + final SignedBeaconBlock block, final BlobsAndProofs blobsAndProofs) { + final List kzgCommitments = + BeaconBlockBodyDeneb.required(block.getMessage().getBody()) + .getBlobKzgCommitments() + .stream() + .map(SszKZGCommitment::getKZGCommitment) + .toList(); + final List blobs = blobsAndProofs.blobs.stream().map(Blob::getBytes).toList(); + try { + if (!spec.atSlot(block.getSlot()) + .miscHelpers() + .isDataAvailable(blobs, kzgCommitments, blobsAndProofs.proofs)) { + return BlobSidecarsAndValidationResult.invalidResult(Collections.emptyList()); + } + } catch (final Exception ex) { + return BlobSidecarsAndValidationResult.invalidResult(Collections.emptyList(), ex); + } + return BlobSidecarsAndValidationResult.validResult(Collections.emptyList()); + } + }; + } + + @Override + public BlobSidecarsAndValidationResult createAvailabilityCheckerAndValidateImmediately( + final SignedBeaconBlock block, final List blobSidecars) { + throw new UnsupportedOperationException("Not available in fork_choice reference tests"); + } + + private record BlobsAndProofs(List blobs, List proofs) {} +} diff --git a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java index 72a8166d77e..9973f0da24f 100644 --- a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java +++ b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java @@ -14,11 +14,15 @@ package tech.pegasys.teku.ethtests.finder; import java.nio.file.Path; +import java.util.Objects; +import java.util.function.Consumer; import tech.pegasys.teku.ethtests.TestFork; import tech.pegasys.teku.ethtests.TestSpecConfig; +import tech.pegasys.teku.networks.Eth2NetworkConfiguration; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecFactory; +import tech.pegasys.teku.spec.config.builder.DenebBuilder; import tech.pegasys.teku.spec.networks.Eth2Network; public class TestDefinition { @@ -55,7 +59,6 @@ public Spec getSpec() { if (spec == null) { createSpec(); } - return spec; } @@ -75,7 +78,26 @@ private void createSpec() { case TestFork.DENEB -> SpecMilestone.DENEB; default -> throw new IllegalArgumentException("Unknown fork: " + fork); }; - spec = TestSpecFactory.create(highestSupportedMilestone, network); + spec = + TestSpecFactory.create( + highestSupportedMilestone, + network, + configBuilder -> configBuilder.denebBuilder(denebConfigModifier(network))); + } + + private Consumer denebConfigModifier(final Eth2Network network) { + return builder -> { + final String trustedSetupFilename = + network.equals(Eth2Network.MAINNET) + ? "mainnet-trusted-setup.txt" + : "minimal-trusted-setup.txt"; + builder.trustedSetupPath(getTrustedSetupPath(trustedSetupFilename)).kzgNoop(false); + }; + } + + private String getTrustedSetupPath(final String trustedSetupFilename) { + return Objects.requireNonNull(Eth2NetworkConfiguration.class.getResource(trustedSetupFilename)) + .toExternalForm(); } public String getTestType() { diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java index d5734016749..ea799fa68e4 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/Spec.java @@ -39,6 +39,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.infrastructure.ssz.Merkleizable; +import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.cache.IndexedAttestationCache; @@ -51,6 +52,7 @@ import tech.pegasys.teku.spec.datastructures.attestation.ValidatableAttestation; import tech.pegasys.teku.spec.datastructures.blobs.SignedBlobSidecarsUnblinder; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.SignedBlindedBlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.SignedBlobSidecar; @@ -376,6 +378,15 @@ public BeaconBlock deserializeBeaconBlock(final Bytes serializedBlock) { .sszDeserialize(serializedBlock); } + public SszList deserializeBlobsInBlock(final Bytes serializedBlobs, final UInt64 slot) { + return atSlot(slot) + .getSchemaDefinitions() + .toVersionDeneb() + .orElseThrow(() -> new RuntimeException("Deneb milestone is required to load blobs")) + .getBlobsInBlockSchema() + .sszDeserialize(serializedBlobs); + } + public BlobSidecar deserializeBlobSidecar(final Bytes serializedBlobSidecar, final UInt64 slot) { return atSlot(slot) .getSchemaDefinitions() diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java index bf706c17838..c2e3fcb0778 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/helpers/MiscHelpers.java @@ -35,6 +35,7 @@ import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.kzg.KZGCommitment; +import tech.pegasys.teku.kzg.KZGProof; import tech.pegasys.teku.spec.config.SpecConfig; import tech.pegasys.teku.spec.constants.NetworkConstants; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; @@ -343,10 +344,6 @@ public boolean isExecutionEnabled(final BeaconState genericState, final BeaconBl return false; } - /** - * Performs data availability by validating the blobs against the kzg commitments from the block. - * It will also check the slot and blockRoot consistency. - */ public boolean isDataAvailable( final UInt64 slot, final Bytes32 beaconBlockRoot, @@ -355,6 +352,13 @@ public boolean isDataAvailable( return false; } + public boolean isDataAvailable( + final List blobs, + final List kzgCommitments, + final List proofs) { + return false; + } + public VersionedHash kzgCommitmentToVersionedHash(final KZGCommitment kzgCommitment) { throw new UnsupportedOperationException("No KZGCommitments before Deneb"); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/deneb/helpers/MiscHelpersDeneb.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/deneb/helpers/MiscHelpersDeneb.java index 716cd6cb872..a6db10899a5 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/deneb/helpers/MiscHelpersDeneb.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/deneb/helpers/MiscHelpersDeneb.java @@ -60,6 +60,9 @@ private static KZG initKZG(final SpecConfigDeneb config) { /** * is_data_available + * + *

Performs data availability by validating the blobs against the kzg commitments from the + * block. It will also check the slot and blockRoot consistency. */ @Override public boolean isDataAvailable( @@ -84,6 +87,18 @@ public boolean isDataAvailable( blobSidecars.stream().map(BlobSidecar::getBlob).map(Blob::getBytes).toList(); final List proofs = blobSidecars.stream().map(BlobSidecar::getKZGProof).toList(); + return isDataAvailable(blobs, kzgCommitments, proofs); + } + + /** + * Simplified version of {@link #isDataAvailable(UInt64, Bytes32, List, List)} which accepts blobs + * and proofs directly instead of blob sidecars + */ + @Override + public boolean isDataAvailable( + final List blobs, + final List kzgCommitments, + final List proofs) { return kzg.verifyBlobKzgProofBatch(blobs, kzgCommitments, proofs); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsDeneb.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsDeneb.java index 5b64343e17d..b697a38d3bf 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsDeneb.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsDeneb.java @@ -16,8 +16,11 @@ import static com.google.common.base.Preconditions.checkArgument; import java.util.Optional; +import tech.pegasys.teku.infrastructure.ssz.SszList; +import tech.pegasys.teku.infrastructure.ssz.schema.SszListSchema; import tech.pegasys.teku.spec.config.SpecConfigDeneb; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecarSchema; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSchema; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecarSchema; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.SignedBlindedBlobSidecarSchema; @@ -74,6 +77,7 @@ public class SchemaDefinitionsDeneb extends SchemaDefinitionsCapella { private final SignedBuilderBidSchema signedBuilderBidSchemaDeneb; private final BlobSchema blobSchema; + private final SszListSchema> blobsInBlockSchema; private final BlobSidecarSchema blobSidecarSchema; private final SignedBlobSidecarSchema signedBlobSidecarSchema; private final BlindedBlobSidecarSchema blindedBlobSidecarSchema; @@ -123,6 +127,7 @@ public SchemaDefinitionsDeneb(final SpecConfigDeneb specConfig) { new SignedBuilderBidSchema("SignedBuilderBidDeneb", builderBidSchemaDeneb); this.blobSchema = new BlobSchema(specConfig); + this.blobsInBlockSchema = SszListSchema.create(blobSchema, specConfig.getMaxBlobsPerBlock()); this.blobSidecarSchema = BlobSidecarSchema.create(blobSchema); this.signedBlobSidecarSchema = SignedBlobSidecarSchema.create(blobSidecarSchema); this.blindedBlobSidecarSchema = BlindedBlobSidecarSchema.create(); @@ -250,6 +255,10 @@ public BlobSchema getBlobSchema() { return blobSchema; } + public SszListSchema> getBlobsInBlockSchema() { + return blobsInBlockSchema; + } + public BlobSidecarSchema getBlobSidecarSchema() { return blobSidecarSchema; } diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/TestSpecFactory.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/TestSpecFactory.java index b163cf60a27..dd58f9b1e08 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/TestSpecFactory.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/TestSpecFactory.java @@ -38,37 +38,23 @@ public static Spec createDefault(final Consumer modifier) { } public static Spec createMinimal(final SpecMilestone specMilestone) { - switch (specMilestone) { - case PHASE0: - return createMinimalPhase0(); - case ALTAIR: - return createMinimalAltair(); - case BELLATRIX: - return createMinimalBellatrix(); - case CAPELLA: - return createMinimalCapella(); - case DENEB: - return createMinimalDeneb(); - default: - throw new IllegalStateException("unsupported milestone"); - } + return switch (specMilestone) { + case PHASE0 -> createMinimalPhase0(); + case ALTAIR -> createMinimalAltair(); + case BELLATRIX -> createMinimalBellatrix(); + case CAPELLA -> createMinimalCapella(); + case DENEB -> createMinimalDeneb(); + }; } public static Spec createMainnet(final SpecMilestone specMilestone) { - switch (specMilestone) { - case PHASE0: - return createMainnetPhase0(); - case ALTAIR: - return createMainnetAltair(); - case BELLATRIX: - return createMainnetBellatrix(); - case CAPELLA: - return createMainnetCapella(); - case DENEB: - return createMainnetDeneb(); - default: - throw new IllegalStateException("unsupported milestone"); - } + return switch (specMilestone) { + case PHASE0 -> createMainnetPhase0(); + case ALTAIR -> createMainnetAltair(); + case BELLATRIX -> createMainnetBellatrix(); + case CAPELLA -> createMainnetCapella(); + case DENEB -> createMainnetDeneb(); + }; } public static Spec createMinimalWithAltairAndBellatrixForkEpoch( @@ -226,44 +212,30 @@ public static Spec create( final SpecMilestone specMilestone, final Eth2Network network, final Consumer configModifier) { - final Consumer actualModifier; - switch (specMilestone) { - case PHASE0: - actualModifier = configModifier; - break; - case ALTAIR: - actualModifier = - configModifier.andThen( - builder -> builder.altairBuilder(altair -> altair.altairForkEpoch(UInt64.ZERO))); - break; - case BELLATRIX: - actualModifier = - configModifier.andThen( - c -> - c.altairBuilder(a -> a.altairForkEpoch(UInt64.ZERO)) - .bellatrixBuilder(m -> m.bellatrixForkEpoch(UInt64.ZERO))); - break; - case CAPELLA: - actualModifier = - configModifier.andThen( - z -> - z.altairBuilder(a -> a.altairForkEpoch(UInt64.ZERO)) - .bellatrixBuilder(b -> b.bellatrixForkEpoch(UInt64.ZERO)) - .capellaBuilder(c -> c.capellaForkEpoch(UInt64.ZERO))); - break; - case DENEB: - actualModifier = - configModifier.andThen( - z -> - z.altairBuilder(a -> a.altairForkEpoch(UInt64.ZERO)) - .bellatrixBuilder(b -> b.bellatrixForkEpoch(UInt64.ZERO)) - .capellaBuilder(c -> c.capellaForkEpoch(UInt64.ZERO)) - .denebBuilder(d -> d.denebForkEpoch(UInt64.ZERO).kzgNoop(true))); - break; - default: - throw new IllegalStateException("unsupported milestone"); - } - return create(SpecConfigLoader.loadConfig(network.configName(), actualModifier), specMilestone); + final Consumer defaultModifier = + switch (specMilestone) { + case PHASE0 -> builder -> {}; + case ALTAIR -> builder -> + builder.altairBuilder(altair -> altair.altairForkEpoch(UInt64.ZERO)); + case BELLATRIX -> builder -> + builder + .altairBuilder(a -> a.altairForkEpoch(UInt64.ZERO)) + .bellatrixBuilder(m -> m.bellatrixForkEpoch(UInt64.ZERO)); + case CAPELLA -> builder -> + builder + .altairBuilder(a -> a.altairForkEpoch(UInt64.ZERO)) + .bellatrixBuilder(b -> b.bellatrixForkEpoch(UInt64.ZERO)) + .capellaBuilder(c -> c.capellaForkEpoch(UInt64.ZERO)); + case DENEB -> builder -> + builder + .altairBuilder(a -> a.altairForkEpoch(UInt64.ZERO)) + .bellatrixBuilder(b -> b.bellatrixForkEpoch(UInt64.ZERO)) + .capellaBuilder(c -> c.capellaForkEpoch(UInt64.ZERO)) + .denebBuilder(d -> d.denebForkEpoch(UInt64.ZERO).kzgNoop(true)); + }; + return create( + SpecConfigLoader.loadConfig(network.configName(), defaultModifier.andThen(configModifier)), + specMilestone); } public static Spec create(