diff --git a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/SidecarBenchmarkConfig.java b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/SidecarBenchmarkConfig.java index 570a59b9245..2a9d34c5bb7 100644 --- a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/SidecarBenchmarkConfig.java +++ b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/SidecarBenchmarkConfig.java @@ -25,12 +25,14 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.MatrixEntry; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; +import tech.pegasys.teku.spec.datastructures.execution.BlobAndCellProofs; import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; import tech.pegasys.teku.spec.logic.versions.electra.helpers.PredicatesElectra; import tech.pegasys.teku.spec.logic.versions.fulu.helpers.MiscHelpersFulu; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsFulu; import tech.pegasys.teku.spec.util.DataStructureUtil; +import tech.pegasys.teku.spec.util.KzgUtil; public class SidecarBenchmarkConfig { final KzgInstances kzgBenchmark; @@ -62,7 +64,11 @@ public class SidecarBenchmarkConfig { .map(SszKZGCommitment::new) .toList(); miscHelpersFulu.setKzg(getKzg(useRustLibrary)); - extendedMatrix = miscHelpersFulu.computeExtendedMatrixAndProofs(blobs); + List blobsAndCellProofs = + blobs.stream() + .map((b) -> KzgUtil.computeBlobAndCellProofs(miscHelpersFulu.getKzg(), b)) + .toList(); + extendedMatrix = miscHelpersFulu.computeExtendedMatrix(blobsAndCellProofs); signedBeaconBlock = dataStructureUtil.randomSignedBeaconBlockWithCommitments( blobKzgCommitmentsSchema.createFromElements(kzgCommitments)); diff --git a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/WithPrecomputeBenchmark.java b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/WithPrecomputeBenchmark.java index 37768d978ee..da9fa75a305 100644 --- a/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/WithPrecomputeBenchmark.java +++ b/eth-benchmark-tests/src/jmh/java/tech/pegasys/teku/benchmarks/kzg/WithPrecomputeBenchmark.java @@ -31,6 +31,7 @@ import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSchema; import tech.pegasys.teku.spec.datastructures.execution.BlobAndCellProofs; import tech.pegasys.teku.spec.datastructures.type.SszKZGProof; +import tech.pegasys.teku.spec.util.KzgUtil; import tech.pegasys.teku.statetransition.datacolumns.DataColumnSidecarArchiveReconstructor; @Fork(1) @@ -55,7 +56,10 @@ public void setup() { @Benchmark public void computeExtendedMatrixAndProofs(final ExecutionPlan plan) { - plan.config.miscHelpersFulu.computeExtendedMatrixAndProofs(plan.config.blobs); + plan.config.miscHelpersFulu.computeExtendedMatrix( + plan.config.blobs.stream() + .map((b) -> KzgUtil.computeBlobAndCellProofs(plan.config.miscHelpersFulu.getKzg(), b)) + .toList()); } @Benchmark diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFulu.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFulu.java index 8c0bc30e39e..96023d38472 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFulu.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFulu.java @@ -52,7 +52,6 @@ import tech.pegasys.teku.spec.datastructures.blobs.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blobs.DataColumnSidecarBuilder; import tech.pegasys.teku.spec.datastructures.blobs.DataColumnSidecarSchema; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.Cell; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumn; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecarFulu; @@ -365,16 +364,6 @@ public List computeDataColumnKzgCommitmentsInclusionProof( beaconBlockBody.getBackingNode(), getBlockBodyKzgCommitmentsGeneralizedIndex()); } - @VisibleForTesting - @Deprecated - public List constructDataColumnSidecarsOld( - final SignedBeaconBlock signedBeaconBlock, final List blobs) { - return constructDataColumnSidecars( - signedBeaconBlock.getMessage(), - signedBeaconBlock.asHeader(), - computeExtendedMatrixAndProofs(blobs)); - } - public List constructDataColumnSidecars( final SignedBeaconBlock signedBeaconBlock, final List blobAndCellProofsList) { @@ -400,40 +389,6 @@ public List constructDataColumnSidecars( extendedMatrix); } - /** - * Return the full ``ExtendedMatrix``. - * - *

This helper demonstrates the relationship between blobs and ``ExtendedMatrix``. - * - *

The data structure for storing cells is implementation-dependent. - * - *

This method uses heavy calculation, use it only when needed - */ - @VisibleForTesting - @Deprecated - public List> computeExtendedMatrixAndProofs(final List blobs) { - return IntStream.range(0, blobs.size()) - .parallel() - .mapToObj( - blobIndex -> { - final List kzgCellAndProofs = - getKzg().computeCellsAndProofs(blobs.get(blobIndex).getBytes()); - final List row = new ArrayList<>(); - for (int cellIndex = 0; cellIndex < kzgCellAndProofs.size(); ++cellIndex) { - row.add( - schemaDefinitionsFulu - .getMatrixEntrySchema() - .create( - kzgCellAndProofs.get(cellIndex).cell(), - kzgCellAndProofs.get(cellIndex).proof(), - cellIndex, - blobIndex)); - } - return row; - }) - .toList(); - } - public List> computeExtendedMatrix( final List blobAndCellProofsList) { return IntStream.range(0, blobAndCellProofsList.size()) diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFuluTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFuluTest.java index 369be420d7d..0c411e54a5a 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFuluTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/fulu/helpers/MiscHelpersFuluTest.java @@ -53,18 +53,19 @@ import tech.pegasys.teku.spec.config.SpecConfigFulu; import tech.pegasys.teku.spec.datastructures.blobs.DataColumnSidecar; import tech.pegasys.teku.spec.datastructures.blobs.DataColumnSidecarSchema; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumn; import tech.pegasys.teku.spec.datastructures.blobs.versions.fulu.DataColumnSidecarFulu; import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockHeader; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlockHeader; +import tech.pegasys.teku.spec.datastructures.execution.BlobAndCellProofs; import tech.pegasys.teku.spec.datastructures.state.BeaconStateTestBuilder; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; import tech.pegasys.teku.spec.logic.common.statetransition.availability.AvailabilityCheckerFactory; import tech.pegasys.teku.spec.logic.versions.electra.helpers.PredicatesElectra; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsFulu; import tech.pegasys.teku.spec.util.DataStructureUtil; +import tech.pegasys.teku.spec.util.KzgUtil; public class MiscHelpersFuluTest { @@ -304,17 +305,23 @@ static void setUpSharedTestData() { MiscHelpersFulu.required(SPEC.forMilestone(SpecMilestone.FULU).miscHelpers()); // Create test data once for all tests - final List blobs = - IntStream.range(0, 4).mapToObj(__ -> dataStructureUtil.randomValidBlob()).toList(); + final List blobsAndCellProofs = + IntStream.range(0, 4) + .mapToObj( + __ -> { + return KzgUtil.computeBlobAndCellProofs( + miscHelpersFulu.getKzg(), dataStructureUtil.randomValidBlob()); + }) + .toList(); sharedSignedBeaconBlock = - dataStructureUtil.randomSignedBeaconBlockWithCommitments(blobs.size()); + dataStructureUtil.randomSignedBeaconBlockWithCommitments(blobsAndCellProofs.size()); sharedOriginalSidecars = miscHelpersFulu.constructDataColumnSidecars( sharedSignedBeaconBlock.getMessage(), sharedSignedBeaconBlock.asHeader(), - miscHelpersFulu.computeExtendedMatrixAndProofs(blobs)); + miscHelpersFulu.computeExtendedMatrix(blobsAndCellProofs)); } @ParameterizedTest(name = "{0} validator custody groups required") diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/KzgUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/KzgUtil.java new file mode 100644 index 00000000000..470e897758b --- /dev/null +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/KzgUtil.java @@ -0,0 +1,28 @@ +/* + * Copyright Consensys Software Inc., 2026 + * + * 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.util; + +import tech.pegasys.teku.kzg.KZG; +import tech.pegasys.teku.kzg.KZGCellAndProof; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; +import tech.pegasys.teku.spec.datastructures.execution.BlobAndCellProofs; + +public class KzgUtil { + + public static BlobAndCellProofs computeBlobAndCellProofs(final KZG kzg, final Blob blob) { + return new BlobAndCellProofs( + blob, + kzg.computeCellsAndProofs(blob.getBytes()).stream().map(KZGCellAndProof::proof).toList()); + } +} diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/SimpleSidecarRetrieverTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/SimpleSidecarRetrieverTest.java index c44f2b2ce76..ef19821783c 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/SimpleSidecarRetrieverTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/SimpleSidecarRetrieverTest.java @@ -51,6 +51,7 @@ import tech.pegasys.teku.spec.datastructures.util.DataColumnSlotAndIdentifier; import tech.pegasys.teku.spec.logic.versions.fulu.helpers.MiscHelpersFulu; import tech.pegasys.teku.spec.util.DataStructureUtil; +import tech.pegasys.teku.spec.util.KzgUtil; import tech.pegasys.teku.statetransition.datacolumns.CanonicalBlockResolverStub; @SuppressWarnings({"JavaCase"}) @@ -127,7 +128,6 @@ private void advanceTimeGradually(final Duration delta) { } @Test - @SuppressWarnings("deprecation") void sanityTest() { final TestPeer custodyPeerMissingData = createCustodyPeer(); final TestPeer custodyPeerHavingData = createCustodyPeer(); @@ -136,7 +136,11 @@ void sanityTest() { final List blobs = Stream.generate(dataStructureUtil::randomValidBlob).limit(1).toList(); final BeaconBlock block = blockResolver.addBlock(10, 1); final List sidecars = - miscHelpers.constructDataColumnSidecarsOld(createSigned(block), blobs); + miscHelpers.constructDataColumnSidecars( + createSigned(block), + blobs.stream() + .map((b) -> KzgUtil.computeBlobAndCellProofs(miscHelpers.getKzg(), b)) + .toList()); final DataColumnSidecar sidecar0 = sidecars.get(columnIndex.intValue()); final DataColumnSlotAndIdentifier id0 = createId(block, columnIndex.intValue()); diff --git a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/recovering/SidecarRetrieverTest.java b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/recovering/SidecarRetrieverTest.java index e7d3c860960..34fbeee57ee 100644 --- a/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/recovering/SidecarRetrieverTest.java +++ b/ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/datacolumns/retriever/recovering/SidecarRetrieverTest.java @@ -38,10 +38,12 @@ import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.config.SpecConfigFulu; import tech.pegasys.teku.spec.datastructures.blobs.DataColumnSidecar; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob; import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock; import tech.pegasys.teku.spec.datastructures.util.DataColumnSlotAndIdentifier; import tech.pegasys.teku.spec.logic.versions.fulu.helpers.MiscHelpersFulu; import tech.pegasys.teku.spec.util.DataStructureUtil; +import tech.pegasys.teku.spec.util.KzgUtil; import tech.pegasys.teku.statetransition.blobs.RemoteOrigin; import tech.pegasys.teku.statetransition.datacolumns.CanonicalBlockResolverStub; import tech.pegasys.teku.statetransition.datacolumns.CustodyGroupCountManager; @@ -162,9 +164,11 @@ void successfulRetrievalShouldRemoveFromPendingRequests() { final int blobCount = 1; final int columnsInDbCount = 1; final BeaconBlock block = blockResolver.addBlock(10, blobCount); + final Blob blob = dataStructureUtil.randomValidBlob(); final List sidecars = - miscHelpers.constructDataColumnSidecarsOld( - dataStructureUtil.signedBlock(block), List.of(dataStructureUtil.randomValidBlob())); + miscHelpers.constructDataColumnSidecars( + dataStructureUtil.signedBlock(block), + List.of(KzgUtil.computeBlobAndCellProofs(miscHelpers.getKzg(), blob))); final List dbColumnIndices = IntStream.range(10, Integer.MAX_VALUE).limit(columnsInDbCount).boxed().toList(); dbColumnIndices.forEach(idx -> assertThat(db.addSidecar(sidecars.get(idx))).isDone()); diff --git a/storage/src/test/java/tech/pegasys/teku/storage/client/BlobReconstructionAbstractTest.java b/storage/src/test/java/tech/pegasys/teku/storage/client/BlobReconstructionAbstractTest.java index 16ddac35643..02de90698b1 100644 --- a/storage/src/test/java/tech/pegasys/teku/storage/client/BlobReconstructionAbstractTest.java +++ b/storage/src/test/java/tech/pegasys/teku/storage/client/BlobReconstructionAbstractTest.java @@ -43,6 +43,7 @@ import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsFulu; import tech.pegasys.teku.spec.util.DataStructureUtil; +import tech.pegasys.teku.spec.util.KzgUtil; public class BlobReconstructionAbstractTest { protected final Spec spec = TestSpecFactory.createMinimalFulu(); @@ -51,7 +52,6 @@ public class BlobReconstructionAbstractTest { @Test @Disabled - @SuppressWarnings("deprecation") public void regenerateValidBlobsAndCellsFile() { reinitializeSpecWithProductionKZG(); @@ -67,7 +67,9 @@ public void regenerateValidBlobsAndCellsFile() { .map( b -> { final var sidecars = - miscHelpers.constructDataColumnSidecarsOld(block, List.of(b)); + miscHelpers.constructDataColumnSidecars( + block, + List.of(KzgUtil.computeBlobAndCellProofs(miscHelpers.getKzg(), b))); return new CellData( b.getBytes().toHexString(), sidecars.stream()