From f2716bc8636d2c45aa68dd604c653ea4f64d9213 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 23 Aug 2023 22:25:39 +1000 Subject: [PATCH 01/15] Convert Eth2SigningRequestBody to record. Add blob_sidecar property --- .../utils/Eth2BlockSigningRequestUtil.java | 2 + .../dsl/utils/Eth2RequestUtils.java | 13 +- .../signing/BlsSigningAcceptanceTest.java | 61 ++++---- .../BlsSigningRootPropertyAcceptanceTest.java | 3 +- .../Eth2BlockSigningAcceptanceTest.java | 6 +- .../Eth2CustomNetworkFileAcceptanceTest.java | 2 +- .../Eth2DepositSigningAcceptanceTest.java | 1 + .../signing/KeyLoadAndSignAcceptanceTest.java | 2 +- .../SlashingExportAcceptanceTest.java | 4 +- .../core/service/http/ArtifactType.java | 3 +- .../signing/eth2/BlindedBlobSidecar.java | 74 +++++++++ .../eth2/Eth2SignForIdentifierHandler.java | 92 ++++++----- .../signing/eth2/Eth2SigningRequestBody.java | 147 +++--------------- .../http/handlers/signing/eth2/KZGProof.java | 86 ++++++++++ 14 files changed, 282 insertions(+), 214 deletions(-) create mode 100644 core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java create mode 100644 core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java index c2c9d987d..d1bf24301 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java @@ -99,6 +99,7 @@ public Eth2SigningRequestBody createBlockV2Request(final BlockRequest blockReque null, null, null, + null, null); } @@ -123,6 +124,7 @@ public Eth2SigningRequestBody createLegacyBlockRequest() { null, null, null, + null, null); } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java index 133bfe578..234245d50 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java @@ -160,6 +160,7 @@ private static Eth2SigningRequestBody createAggregateAndProof() { null, null, null, + null, null); } @@ -184,6 +185,7 @@ private static Eth2SigningRequestBody createAggregationSlot() { null, null, null, + null, null); } @@ -212,6 +214,7 @@ private static Eth2SigningRequestBody createRandaoReveal() { null, null, null, + null, null); } @@ -236,6 +239,7 @@ private static Eth2SigningRequestBody createVoluntaryExit() { null, null, null, + null, null); } @@ -266,6 +270,7 @@ private static Eth2SigningRequestBody createDepositRequest() { null, null, null, + null, null); } @@ -301,6 +306,7 @@ public static Eth2SigningRequestBody createAttestationRequest( null, null, null, + null, null); } @@ -353,6 +359,7 @@ public static Eth2SigningRequestBody createBlockRequest( null, null, null, + null, null); } @@ -411,6 +418,7 @@ private static Eth2SigningRequestBody createSyncCommitteeMessageRequest() { syncCommitteeMessage, null, null, + null, null); } @@ -448,6 +456,7 @@ private static Eth2SigningRequestBody createSyncCommitteeSelectionProofRequest() null, getSyncAggregatorSelectionData(SLOT, subcommitteeIndex), null, + null, null); } @@ -488,6 +497,7 @@ private static Eth2SigningRequestBody createSyncCommitteeContributionAndProofReq null, null, getContributionAndProof(), + null, null); } @@ -516,7 +526,8 @@ private static Eth2SigningRequestBody createValidatorRegistrationRequest() { null, null, null, - validatorRegistration); + validatorRegistration, + null); } private static tech.pegasys.teku.api.schema.altair.ContributionAndProof diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java index 7a09b01da..add73e0db 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java @@ -246,21 +246,22 @@ public void failsIfSigningRootDoesNotMatchSigningData(final ArtifactType artifac final Eth2SigningRequestBody request = Eth2RequestUtils.createCannedRequest(artifactType); final Eth2SigningRequestBody requestWithMismatchedSigningRoot = new Eth2SigningRequestBody( - request.getType(), + request.type(), Bytes32.ZERO, - request.getForkInfo(), - request.getBlock(), - request.getBlockRequest(), - request.getAttestation(), - request.getAggregationSlot(), - request.getAggregateAndProof(), - request.getVoluntaryExit(), - request.getRandaoReveal(), - request.getDeposit(), - request.getSyncCommitteeMessage(), - request.getSyncAggregatorSelectionData(), - request.getContributionAndProof(), - request.getValidatorRegistration()); + request.forkInfo(), + request.block(), + request.blockRequest(), + request.attestation(), + request.aggregationSlot(), + request.aggregateAndProof(), + request.voluntaryExit(), + request.randaoReveal(), + request.deposit(), + request.syncCommitteeMessage(), + request.syncAggregatorSelectionData(), + request.contributionAndProof(), + request.validatorRegistration(), + request.blindedBlobSidecar()); final Response response = signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), requestWithMismatchedSigningRoot); @@ -284,21 +285,22 @@ public void ableToSignWithoutSigningRootField(final ContentType acceptableConten final Eth2SigningRequestBody requestWithMismatchedSigningRoot = new Eth2SigningRequestBody( - request.getType(), + request.type(), null, - request.getForkInfo(), - request.getBlock(), - request.getBlockRequest(), - request.getAttestation(), - request.getAggregationSlot(), - request.getAggregateAndProof(), - request.getVoluntaryExit(), - request.getRandaoReveal(), - request.getDeposit(), - request.getSyncCommitteeMessage(), - request.getSyncAggregatorSelectionData(), - request.getContributionAndProof(), - request.getValidatorRegistration()); + request.forkInfo(), + request.block(), + request.blockRequest(), + request.attestation(), + request.aggregationSlot(), + request.aggregateAndProof(), + request.voluntaryExit(), + request.randaoReveal(), + request.deposit(), + request.syncCommitteeMessage(), + request.syncAggregatorSelectionData(), + request.contributionAndProof(), + request.validatorRegistration(), + request.blindedBlobSidecar()); final Response response = signer.eth2Sign( @@ -335,8 +337,7 @@ private void signAndVerifySignature( signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, acceptMediaType); final Bytes signature = verifyAndGetSignatureResponse(response, expectedContentType(acceptMediaType)); - final BLSSignature expectedSignature = - BLS.sign(KEY_PAIR.getSecretKey(), request.getSigningRoot()); + final BLSSignature expectedSignature = BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()); assertThat(signature).isEqualTo(expectedSignature.toBytesCompressed()); } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java index d5ba83f51..6719f2cb1 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java @@ -83,8 +83,7 @@ private void signAndVerifySignature(final String signingRootProperty) signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), modifiedJsonBody, acceptMediaType); final Bytes signature = verifyAndGetSignatureResponse(response, expectedContentType(acceptMediaType)); - final BLSSignature expectedSignature = - BLS.sign(KEY_PAIR.getSecretKey(), request.getSigningRoot()); + final BLSSignature expectedSignature = BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()); assertThat(signature).isEqualTo(expectedSignature.toBytesCompressed()); } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2BlockSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2BlockSigningAcceptanceTest.java index 3b524e965..ec329e56f 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2BlockSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2BlockSigningAcceptanceTest.java @@ -69,8 +69,7 @@ void signAndVerifyBlockV2Signature(final SpecMilestone specMilestone) throws Exc final Response response = signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, ContentType.JSON); final Bytes signature = verifyAndGetSignatureResponse(response, ContentType.JSON); - final BLSSignature expectedSignature = - BLS.sign(KEY_PAIR.getSecretKey(), request.getSigningRoot()); + final BLSSignature expectedSignature = BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()); assertThat(signature).isEqualTo(expectedSignature.toBytesCompressed()); } @@ -83,8 +82,7 @@ void signAndVerifyLegacyBlockSignature() throws Exception { final Response response = signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, ContentType.JSON); final Bytes signature = verifyAndGetSignatureResponse(response, ContentType.JSON); - final BLSSignature expectedSignature = - BLS.sign(KEY_PAIR.getSecretKey(), request.getSigningRoot()); + final BLSSignature expectedSignature = BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()); assertThat(signature).isEqualTo(expectedSignature.toBytesCompressed()); } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2CustomNetworkFileAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2CustomNetworkFileAcceptanceTest.java index 53829369e..5862c24bb 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2CustomNetworkFileAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2CustomNetworkFileAcceptanceTest.java @@ -89,7 +89,7 @@ void signAndVerifyBlockV2SignatureForAllEnabledMilestones() throws Exception { createBlockV2SigningRequest(spec, forkAndSpecMilestone); final Bytes signingRootSignature = sendSignRequestAndReceiveSignature(request); final Bytes expectedSigningRootSignature = - calculateSigningRootSignature(request.getSigningRoot()); + calculateSigningRootSignature(request.signingRoot()); assertThat(signingRootSignature).isEqualTo(expectedSigningRootSignature); } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java index 6d583e90c..0573e4cd2 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java @@ -117,6 +117,7 @@ private void verifyDepositData(final Map depositData) throws IOE null, null, null, + null, null); final Response response = signer.eth2Sign(publicKey, requestBody, TEXT); diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/KeyLoadAndSignAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/KeyLoadAndSignAcceptanceTest.java index 6d9167440..86ed443fd 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/KeyLoadAndSignAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/KeyLoadAndSignAcceptanceTest.java @@ -154,7 +154,7 @@ public void unusedFieldsInRequestDoesNotAffectSigning() throws JsonProcessingExc new JsonObject(ETH_2_INTERFACE_OBJECT_MAPPER.writeValueAsString(blockRequest)); final String body = jsonObject.put("unknownField", "someValue").toString(); final String expectedSignature = - BLS.sign(BLS_KEY_PAIR.getSecretKey(), blockRequest.getSigningRoot()).toString(); + BLS.sign(BLS_KEY_PAIR.getSecretKey(), blockRequest.signingRoot()).toString(); given() .baseUri(signer.getUrl()) diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java index 35c3f3f6e..a50443374 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java @@ -113,9 +113,9 @@ void slashingDataIsExported(@TempDir final Path testDirectory) throws IOExceptio assertThat(artifacts.getSignedAttestations()).hasSize(1); final SignedAttestation attestation = artifacts.getSignedAttestations().get(0); assertThat(attestation.getSourceEpoch().toLong()) - .isEqualTo(request.getAttestation().source.epoch.longValue()); + .isEqualTo(request.attestation().source.epoch.longValue()); assertThat(attestation.getTargetEpoch().toLong()) - .isEqualTo(request.getAttestation().target.epoch.longValue()); + .isEqualTo(request.attestation().target.epoch.longValue()); assertThat(attestation.getSigningRoot()).isNotNull(); } } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/ArtifactType.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/ArtifactType.java index b9c99f6cb..d4f0982a6 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/ArtifactType.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/ArtifactType.java @@ -24,5 +24,6 @@ public enum ArtifactType { SYNC_COMMITTEE_MESSAGE, SYNC_COMMITTEE_SELECTION_PROOF, SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF, - VALIDATOR_REGISTRATION + VALIDATOR_REGISTRATION, + BLOB_SIDECAR } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java new file mode 100644 index 000000000..97e0716ef --- /dev/null +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java @@ -0,0 +1,74 @@ +/* + * Copyright 2023 ConsenSys AG. + * + * 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.web3signer.core.service.http.handlers.signing.eth2; + +import tech.pegasys.teku.api.schema.KZGCommitment; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.SpecVersion; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecarSchema; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.tuweni.bytes.Bytes32; + +public record BlindedBlobSidecar( + @JsonProperty("block_root") Bytes32 blockRoot, + @JsonProperty("index") UInt64 index, + @JsonProperty("slot") UInt64 slot, + @JsonProperty("block_parent_root") Bytes32 blockParentRoot, + @JsonProperty("proposer_index") UInt64 proposerIndex, + @JsonProperty("blob_root") Bytes32 blobRoot, + @JsonProperty("kzg_commitment") KZGCommitment kzgCommitment, + @JsonProperty("kzg_proof") KZGProof kzgProof) { + + public static BlindedBlobSidecar fromInternalBlindedBlobSidecar( + tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar sidecar) { + return new BlindedBlobSidecar( + sidecar.getBlockRoot(), + sidecar.getIndex(), + sidecar.getSlot(), + sidecar.getBlockParentRoot(), + sidecar.getProposerIndex(), + sidecar.getBlobRoot(), + new KZGCommitment(sidecar.getKZGCommitment()), + new KZGProof(sidecar.getKZGProof())); + } + + public static BlindedBlobSidecar fromInternalBlobSidecar(final BlobSidecar sidecar) { + return new BlindedBlobSidecar( + sidecar.getBlockRoot(), + sidecar.getIndex(), + sidecar.getSlot(), + sidecar.getBlockParentRoot(), + sidecar.getProposerIndex(), + sidecar.getBlob().hashTreeRoot(), + new KZGCommitment(sidecar.getKZGCommitment()), + new KZGProof(sidecar.getKZGProof())); + } + + public tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar + asInternalBlindedBlobSidecar(final SpecVersion spec) { + final BlindedBlobSidecarSchema blindedBlobSidecarSchema = + spec.getSchemaDefinitions().toVersionDeneb().orElseThrow().getBlindedBlobSidecarSchema(); + return new tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar( + blindedBlobSidecarSchema, + blockRoot, + index, + slot, + blockParentRoot, + proposerIndex, + blobRoot, + kzgCommitment.asInternalKZGCommitment(), + kzgProof.asInternalKZGProof()); + } +} diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java index 9bfbfabea..230f1b344 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java @@ -98,11 +98,11 @@ public void handle(final RoutingContext routingContext) { } final Bytes signingRoot = computeSigningRoot(eth2SigningRequestBody); - if (eth2SigningRequestBody.getSigningRoot() != null) { + if (eth2SigningRequestBody.signingRoot() != null) { checkArgument( - eth2SigningRequestBody.getSigningRoot().equals(signingRoot), + eth2SigningRequestBody.signingRoot().equals(signingRoot), "Signing root %s must match signing computed signing root %s from data", - eth2SigningRequestBody.getSigningRoot(), + eth2SigningRequestBody.signingRoot(), signingRoot); } @@ -170,8 +170,8 @@ private boolean maySign( final Bytes publicKey, final Bytes signingRoot, final Eth2SigningRequestBody eth2SigningRequestBody) { - final ForkInfo forkInfo = eth2SigningRequestBody.getForkInfo(); - switch (eth2SigningRequestBody.getType()) { + final ForkInfo forkInfo = eth2SigningRequestBody.forkInfo(); + switch (eth2SigningRequestBody.type()) { case BLOCK: case BLOCK_V2: try (final TimingContext ignored = @@ -180,7 +180,7 @@ private boolean maySign( publicKey, signingRoot, getBlockSlot(eth2SigningRequestBody), forkInfo); } case ATTESTATION: - final AttestationData attestation = eth2SigningRequestBody.getAttestation(); + final AttestationData attestation = eth2SigningRequestBody.attestation(); try (final TimingContext ignored = slashingMetrics.getDatabaseTimer().labels("attestation").startTimer()) { return slashingProtection @@ -199,10 +199,10 @@ private boolean maySign( private UInt64 getBlockSlot(final Eth2SigningRequestBody eth2SigningRequestBody) { final UInt64 blockSlot; - if (eth2SigningRequestBody.getType() == ArtifactType.BLOCK) { - blockSlot = UInt64.valueOf(eth2SigningRequestBody.getBlock().slot.bigIntegerValue()); + if (eth2SigningRequestBody.type() == ArtifactType.BLOCK) { + blockSlot = UInt64.valueOf(eth2SigningRequestBody.block().slot.bigIntegerValue()); } else { - final BlockRequest blockRequest = eth2SigningRequestBody.getBlockRequest(); + final BlockRequest blockRequest = eth2SigningRequestBody.blockRequest(); switch (blockRequest.getVersion()) { case PHASE0: case ALTAIR: @@ -229,64 +229,61 @@ private boolean maySignBlock( } private Bytes computeSigningRoot(final Eth2SigningRequestBody body) { - switch (body.getType()) { + switch (body.type()) { case BLOCK: - checkArgument(body.getBlock() != null, "block must be specified"); + checkArgument(body.block() != null, "block must be specified"); return signingRootUtil.signingRootForSignBlock( - body.getBlock().asInternalBeaconBlock(eth2Spec), - body.getForkInfo().asInternalForkInfo()); + body.block().asInternalBeaconBlock(eth2Spec), body.forkInfo().asInternalForkInfo()); case BLOCK_V2: - checkArgument(body.getBlockRequest() != null, "beacon_block must be specified"); + checkArgument(body.blockRequest() != null, "beacon_block must be specified"); final Bytes blockV2SigningRoot; - switch (body.getBlockRequest().getVersion()) { + switch (body.blockRequest().getVersion()) { case PHASE0: case ALTAIR: blockV2SigningRoot = signingRootUtil.signingRootForSignBlock( - body.getBlockRequest().getBeaconBlock().asInternalBeaconBlock(eth2Spec), - body.getForkInfo().asInternalForkInfo()); + body.blockRequest().getBeaconBlock().asInternalBeaconBlock(eth2Spec), + body.forkInfo().asInternalForkInfo()); break; case BELLATRIX: default: blockV2SigningRoot = signingRootUtil.signingRootForSignBlockHeader( - body.getBlockRequest().getBeaconBlockHeader().asInternalBeaconBlockHeader(), - body.getForkInfo().asInternalForkInfo()); + body.blockRequest().getBeaconBlockHeader().asInternalBeaconBlockHeader(), + body.forkInfo().asInternalForkInfo()); break; } return blockV2SigningRoot; case ATTESTATION: - checkArgument(body.getAttestation() != null, "attestation must be specified"); + checkArgument(body.attestation() != null, "attestation must be specified"); return signingRootUtil.signingRootForSignAttestationData( - body.getAttestation().asInternalAttestationData(), - body.getForkInfo().asInternalForkInfo()); + body.attestation().asInternalAttestationData(), body.forkInfo().asInternalForkInfo()); case AGGREGATE_AND_PROOF: - checkArgument(body.getAggregateAndProof() != null, "aggregateAndProof must be specified"); + checkArgument(body.aggregateAndProof() != null, "aggregateAndProof must be specified"); return signingRootUtil.signingRootForSignAggregateAndProof( - body.getAggregateAndProof().asInternalAggregateAndProof(eth2Spec), - body.getForkInfo().asInternalForkInfo()); + body.aggregateAndProof().asInternalAggregateAndProof(eth2Spec), + body.forkInfo().asInternalForkInfo()); case AGGREGATION_SLOT: - checkArgument(body.getAggregationSlot() != null, "aggregationSlot must be specified"); + checkArgument(body.aggregationSlot() != null, "aggregationSlot must be specified"); return signingRootUtil.signingRootForSignAggregationSlot( - body.getAggregationSlot().getSlot(), body.getForkInfo().asInternalForkInfo()); + body.aggregationSlot().getSlot(), body.forkInfo().asInternalForkInfo()); case RANDAO_REVEAL: - checkArgument(body.getRandaoReveal() != null, "randaoReveal must be specified"); + checkArgument(body.randaoReveal() != null, "randaoReveal must be specified"); return signingRootUtil.signingRootForRandaoReveal( - body.getRandaoReveal().getEpoch(), body.getForkInfo().asInternalForkInfo()); + body.randaoReveal().getEpoch(), body.forkInfo().asInternalForkInfo()); case VOLUNTARY_EXIT: - checkArgument(body.getVoluntaryExit() != null, "voluntaryExit must be specified"); + checkArgument(body.voluntaryExit() != null, "voluntaryExit must be specified"); return signingRootUtil.signingRootForSignVoluntaryExit( - body.getVoluntaryExit().asInternalVoluntaryExit(), - body.getForkInfo().asInternalForkInfo()); + body.voluntaryExit().asInternalVoluntaryExit(), body.forkInfo().asInternalForkInfo()); case DEPOSIT: - checkArgument(body.getDeposit() != null, "deposit must be specified"); + checkArgument(body.deposit() != null, "deposit must be specified"); final Bytes32 depositDomain = - computeDomain(Domain.DEPOSIT, body.getDeposit().getGenesisForkVersion(), Bytes32.ZERO); + computeDomain(Domain.DEPOSIT, body.deposit().getGenesisForkVersion(), Bytes32.ZERO); return DepositSigningRootUtil.computeSigningRoot( - body.getDeposit().asInternalDepositMessage(), depositDomain); + body.deposit().asInternalDepositMessage(), depositDomain); case SYNC_COMMITTEE_MESSAGE: - final SyncCommitteeMessage syncCommitteeMessage = body.getSyncCommitteeMessage(); + final SyncCommitteeMessage syncCommitteeMessage = body.syncCommitteeMessage(); checkArgument(syncCommitteeMessage != null, "SyncCommitteeMessage must be specified"); return signingRootFromSyncCommitteeUtils( syncCommitteeMessage.getSlot(), @@ -294,10 +291,10 @@ private Bytes computeSigningRoot(final Eth2SigningRequestBody body) { utils.getSyncCommitteeMessageSigningRoot( syncCommitteeMessage.getBeaconBlockRoot(), eth2Spec.computeEpochAtSlot(syncCommitteeMessage.getSlot()), - body.getForkInfo().asInternalForkInfo())); + body.forkInfo().asInternalForkInfo())); case SYNC_COMMITTEE_SELECTION_PROOF: final SyncAggregatorSelectionData syncAggregatorSelectionData = - body.getSyncAggregatorSelectionData(); + body.syncAggregatorSelectionData(); checkArgument( syncAggregatorSelectionData != null, "SyncAggregatorSelectionData is required"); return signingRootFromSyncCommitteeUtils( @@ -305,23 +302,32 @@ private Bytes computeSigningRoot(final Eth2SigningRequestBody body) { utils -> utils.getSyncAggregatorSelectionDataSigningRoot( asInternalSyncAggregatorSelectionData(syncAggregatorSelectionData), - body.getForkInfo().asInternalForkInfo())); + body.forkInfo().asInternalForkInfo())); case SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF: - final ContributionAndProof contributionAndProof = body.getContributionAndProof(); + final ContributionAndProof contributionAndProof = body.contributionAndProof(); checkArgument(contributionAndProof != null, "ContributionAndProof is required"); return signingRootFromSyncCommitteeUtils( contributionAndProof.contribution.slot, utils -> utils.getContributionAndProofSigningRoot( asInternalContributionAndProof(contributionAndProof), - body.getForkInfo().asInternalForkInfo())); + body.forkInfo().asInternalForkInfo())); case VALIDATOR_REGISTRATION: - final ValidatorRegistration validatorRegistration = body.getValidatorRegistration(); + final ValidatorRegistration validatorRegistration = body.validatorRegistration(); checkArgument(validatorRegistration != null, "ValidatorRegistration is required"); return signingRootUtil.signingRootForValidatorRegistration( validatorRegistration.asInternalValidatorRegistration()); + case BLOB_SIDECAR: + // handles both blinded/blob sidecar + final BlindedBlobSidecar blindedBlobSidecar = body.blindedBlobSidecar(); + checkArgument(blindedBlobSidecar != null, "BlobSidecar is required"); + return signingRootUtil.signingRootForBlindedBlobSidecar( + blindedBlobSidecar.asInternalBlindedBlobSidecar( + eth2Spec.atSlot(blindedBlobSidecar.slot())), + body.forkInfo().asInternalForkInfo()); + default: - throw new IllegalStateException("Signing root unimplemented for type " + body.getType()); + throw new IllegalStateException("Signing root unimplemented for type " + body.type()); } } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java index be3dbfc0d..ef7be492f 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java @@ -20,135 +20,24 @@ import tech.pegasys.web3signer.core.service.http.ArtifactType; import com.fasterxml.jackson.annotation.JsonAlias; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.tuweni.bytes.Bytes; -public class Eth2SigningRequestBody { - private final ArtifactType type; - private final Bytes signingRoot; - private final ForkInfo forkInfo; - private final BeaconBlock beaconBlock; // phase 0 - private final BlockRequest blockRequest; // altair and onward - private final AttestationData attestation; - private final AggregationSlot aggregationSlot; - private final AggregateAndProof aggregateAndProof; - private final VoluntaryExit voluntaryExit; - private final RandaoReveal randaoReveal; - private final DepositMessage deposit; - private final SyncCommitteeMessage syncCommitteeMessage; - private final SyncAggregatorSelectionData syncAggregatorSelectionData; - private final ContributionAndProof contributionAndProof; - private final ValidatorRegistration validatorRegistration; - - @JsonCreator - public Eth2SigningRequestBody( - @JsonProperty(value = "type", required = true) final ArtifactType type, - @JsonProperty("signing_root") @JsonAlias("signingRoot") final Bytes signingRoot, - @JsonProperty("fork_info") final ForkInfo forkInfo, - @JsonProperty("block") final BeaconBlock block, - @JsonProperty("beacon_block") final BlockRequest blockRequest, - @JsonProperty("attestation") final AttestationData attestation, - @JsonProperty("aggregation_slot") final AggregationSlot aggregationSlot, - @JsonProperty("aggregate_and_proof") final AggregateAndProof aggregateAndProof, - @JsonProperty("voluntary_exit") final VoluntaryExit voluntaryExit, - @JsonProperty("randao_reveal") final RandaoReveal randaoReveal, - @JsonProperty("deposit") final DepositMessage deposit, - @JsonProperty("sync_committee_message") final SyncCommitteeMessage syncCommitteeMessage, - @JsonProperty("sync_aggregator_selection_data") - final SyncAggregatorSelectionData syncAggregatorSelectionData, - @JsonProperty("contribution_and_proof") final ContributionAndProof contributionAndProof, - @JsonProperty("validator_registration") final ValidatorRegistration validatorRegistration) { - this.type = type; - this.signingRoot = signingRoot; - this.forkInfo = forkInfo; - this.beaconBlock = block; - this.blockRequest = blockRequest; - this.attestation = attestation; - this.aggregationSlot = aggregationSlot; - this.aggregateAndProof = aggregateAndProof; - this.voluntaryExit = voluntaryExit; - this.randaoReveal = randaoReveal; - this.deposit = deposit; - this.syncCommitteeMessage = syncCommitteeMessage; - this.syncAggregatorSelectionData = syncAggregatorSelectionData; - this.contributionAndProof = contributionAndProof; - this.validatorRegistration = validatorRegistration; - } - - @JsonProperty("type") - public ArtifactType getType() { - return type; - } - - @JsonProperty("fork_info") - public ForkInfo getForkInfo() { - return forkInfo; - } - - @JsonProperty("block") - public BeaconBlock getBlock() { - return beaconBlock; - } - - @JsonProperty("beacon_block") - public BlockRequest getBlockRequest() { - return blockRequest; - } - - @JsonProperty("attestation") - public AttestationData getAttestation() { - return attestation; - } - - @JsonProperty("signing_root") - @JsonAlias("signingRoot") - public Bytes getSigningRoot() { - return signingRoot; - } - - @JsonProperty("aggregation_slot") - public AggregationSlot getAggregationSlot() { - return aggregationSlot; - } - - @JsonProperty("aggregate_and_proof") - public AggregateAndProof getAggregateAndProof() { - return aggregateAndProof; - } - - @JsonProperty("voluntary_exit") - public VoluntaryExit getVoluntaryExit() { - return voluntaryExit; - } - - @JsonProperty("randao_reveal") - public RandaoReveal getRandaoReveal() { - return randaoReveal; - } - - @JsonProperty("deposit") - public DepositMessage getDeposit() { - return deposit; - } - - @JsonProperty("sync_committee_message") - public SyncCommitteeMessage getSyncCommitteeMessage() { - return syncCommitteeMessage; - } - - @JsonProperty("sync_aggregator_selection_data") - public SyncAggregatorSelectionData getSyncAggregatorSelectionData() { - return syncAggregatorSelectionData; - } - - @JsonProperty("contribution_and_proof") - public ContributionAndProof getContributionAndProof() { - return contributionAndProof; - } - - @JsonProperty("validator_registration") - public ValidatorRegistration getValidatorRegistration() { - return validatorRegistration; - } -} +public record Eth2SigningRequestBody( + @JsonProperty(value = "type", required = true) ArtifactType type, + @JsonProperty("signing_root") @JsonAlias("signingRoot") Bytes signingRoot, + @JsonProperty("fork_info") ForkInfo forkInfo, + @JsonProperty("block") BeaconBlock block, + @JsonProperty("beacon_block") BlockRequest blockRequest, + @JsonProperty("attestation") AttestationData attestation, + @JsonProperty("aggregation_slot") AggregationSlot aggregationSlot, + @JsonProperty("aggregate_and_proof") AggregateAndProof aggregateAndProof, + @JsonProperty("voluntary_exit") VoluntaryExit voluntaryExit, + @JsonProperty("randao_reveal") RandaoReveal randaoReveal, + @JsonProperty("deposit") DepositMessage deposit, + @JsonProperty("sync_committee_message") SyncCommitteeMessage syncCommitteeMessage, + @JsonProperty("sync_aggregator_selection_data") + SyncAggregatorSelectionData syncAggregatorSelectionData, + @JsonProperty("contribution_and_proof") ContributionAndProof contributionAndProof, + @JsonProperty("validator_registration") ValidatorRegistration validatorRegistration, + @JsonProperty("blob_sidecar") BlindedBlobSidecar blindedBlobSidecar) {} diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java new file mode 100644 index 000000000..c7c11f8e1 --- /dev/null +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java @@ -0,0 +1,86 @@ +/* + * Copyright 2022 ConsenSys AG. + * + * 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.web3signer.core.service.http.handlers.signing.eth2; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Objects; + +import org.apache.tuweni.bytes.Bytes; + +public class KZGProof { + /** The number of bytes in this value - i.e. 48 */ + private static final int SIZE = 48; + + private final Bytes bytes; + + public KZGProof(final Bytes bytes) { + checkArgument( + bytes.size() == SIZE, + "Bytes%s should be %s bytes, but was %s bytes.", + SIZE, + SIZE, + bytes.size()); + this.bytes = bytes; + } + + public KZGProof(final tech.pegasys.teku.kzg.KZGProof kzgProof) { + this(kzgProof.toSSZBytes()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final KZGProof other = (KZGProof) o; + return bytes.equals(other.bytes); + } + + @Override + public int hashCode() { + return Objects.hash(bytes); + } + + @Override + public String toString() { + return bytes.toString(); + } + + public static KZGProof fromHexString(final String value) { + try { + return new KZGProof(tech.pegasys.teku.kzg.KZGProof.fromHexString(value)); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("KZGProof " + value + " is invalid: " + e.getMessage(), e); + } + } + + public String toHexString() { + return bytes.toHexString(); + } + + public Bytes toBytes() { + return bytes; + } + + public static KZGProof empty() { + return new KZGProof(Bytes.wrap(new byte[SIZE])); + } + + public tech.pegasys.teku.kzg.KZGProof asInternalKZGProof() { + return tech.pegasys.teku.kzg.KZGProof.fromSSZBytes(bytes); + } +} From 3a26342ef954745f66d7e2545af3ef6bce3a844b Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 23 Aug 2023 22:33:00 +1000 Subject: [PATCH 02/15] Update SigningObjectMapperFactory with KZGCommitment and KZGProof --- .../http/SigningObjectMapperFactory.java | 11 +++++++ .../eth2/json/KZGProofDeserializer.java | 30 ++++++++++++++++++ .../signing/eth2/json/KZGProofSerializer.java | 31 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java create mode 100644 core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/SigningObjectMapperFactory.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/SigningObjectMapperFactory.java index 0243dce4d..9864d1f87 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/SigningObjectMapperFactory.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/SigningObjectMapperFactory.java @@ -14,6 +14,7 @@ import tech.pegasys.teku.api.schema.BLSPubKey; import tech.pegasys.teku.api.schema.BLSSignature; +import tech.pegasys.teku.api.schema.KZGCommitment; import tech.pegasys.teku.infrastructure.bytes.Bytes20; import tech.pegasys.teku.infrastructure.bytes.Bytes4; import tech.pegasys.teku.infrastructure.jackson.deserializers.bytes.Bytes32Deserializer; @@ -30,13 +31,18 @@ import tech.pegasys.teku.provider.BLSPubKeySerializer; import tech.pegasys.teku.provider.BLSSignatureDeserializer; import tech.pegasys.teku.provider.BLSSignatureSerializer; +import tech.pegasys.teku.provider.KZGCommitmentDeserializer; +import tech.pegasys.teku.provider.KZGCommitmentSerializer; import tech.pegasys.teku.provider.SszBitvectorSerializer; import tech.pegasys.web3signer.common.JacksonSerializers.HexDeserialiser; import tech.pegasys.web3signer.common.JacksonSerializers.HexSerialiser; import tech.pegasys.web3signer.common.JacksonSerializers.StringUInt64Deserializer; import tech.pegasys.web3signer.common.JacksonSerializers.StringUInt64Serialiser; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlockRequest; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.KZGProof; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.json.BlockRequestDeserializer; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.json.KZGProofDeserializer; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.json.KZGProofSerializer; import tech.pegasys.web3signer.signing.config.metadata.parser.SigningMetadataModule; import tech.pegasys.web3signer.signing.config.metadata.parser.SigningMetadataModule.Bytes32Serializer; @@ -98,6 +104,11 @@ private Module web3SignerMappers() { module.addDeserializer(Bytes20.class, new SigningMetadataModule.Bytes20Deserializer()); module.addSerializer(Bytes20.class, new SigningMetadataModule.Bytes20Serializer()); + module.addSerializer(KZGCommitment.class, new KZGCommitmentSerializer()); + module.addDeserializer(KZGCommitment.class, new KZGCommitmentDeserializer()); + + module.addSerializer(KZGProof.class, new KZGProofSerializer()); + module.addDeserializer(KZGProof.class, new KZGProofDeserializer()); return module; } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java new file mode 100644 index 000000000..089f926ec --- /dev/null +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2022 ConsenSys AG. + * + * 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.web3signer.core.service.http.handlers.signing.eth2.json; + +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.KZGProof; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import org.apache.tuweni.bytes.Bytes; + +public class KZGProofDeserializer extends JsonDeserializer { + @Override + public KZGProof deserialize(final JsonParser p, final DeserializationContext ignore) + throws IOException { + return new KZGProof(Bytes.fromHexString(p.getValueAsString())); + } +} diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java new file mode 100644 index 000000000..5849c28fd --- /dev/null +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2022 ConsenSys AG. + * + * 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.web3signer.core.service.http.handlers.signing.eth2.json; + +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.KZGProof; + +import java.io.IOException; +import java.util.Locale; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class KZGProofSerializer extends JsonSerializer { + @Override + public void serialize( + final KZGProof value, final JsonGenerator gen, final SerializerProvider serializers) + throws IOException { + gen.writeString(value.toHexString().toLowerCase(Locale.ROOT)); + } +} From 1d3bdb0f023aadb6dad4e1f06ec9887e9c2dbcae Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 23 Aug 2023 23:14:25 +1000 Subject: [PATCH 03/15] Builder for Eth2SigningRequest in AT --- .../utils/Eth2BlockSigningRequestUtil.java | 46 +-- .../dsl/utils/Eth2RequestUtils.java | 279 ++++++------------ .../utils/Eth2SigningRequestBodyBuilder.java | 162 ++++++++++ .../Eth2DepositSigningAcceptanceTest.java | 22 +- 4 files changed, 269 insertions(+), 240 deletions(-) create mode 100644 acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java index d1bf24301..8616972e9 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2BlockSigningRequestUtil.java @@ -84,23 +84,12 @@ public Eth2SigningRequestBody createBlockV2Request() { } public Eth2SigningRequestBody createBlockV2Request(final BlockRequest blockRequest) { - return new Eth2SigningRequestBody( - ArtifactType.BLOCK_V2, - signingRoot, - forkInfo, - null, - blockRequest, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.BLOCK_V2) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withBlockRequest(blockRequest) + .build(); } public Eth2SigningRequestBody createLegacyBlockRequest() { @@ -109,23 +98,12 @@ public Eth2SigningRequestBody createLegacyBlockRequest() { "Only PHASE0 spec is supported to create legacy BLOCK type signing request"); } - return new Eth2SigningRequestBody( - ArtifactType.BLOCK, - signingRoot, - forkInfo, - getBeaconBlock(), - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.BLOCK) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withBlock(getBeaconBlock()) + .build(); } private BeaconBlockHeader getBeaconBlockHeader() { diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java index 234245d50..d9c109d9f 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java @@ -13,6 +13,7 @@ package tech.pegasys.web3signer.dsl.utils; import static java.util.Collections.emptyList; +import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar.fromInternalBlindedBlobSidecar; import static tech.pegasys.web3signer.core.util.DepositSigningRootUtil.computeDomain; import tech.pegasys.teku.api.schema.AggregateAndProof; @@ -33,6 +34,7 @@ import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.constants.Domain; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.ContributionAndProof; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncAggregatorSelectionData; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncCommitteeContribution; @@ -113,6 +115,8 @@ public static Eth2SigningRequestBody createCannedRequest(final ArtifactType arti return createSyncCommitteeContributionAndProofRequest(); case VALIDATOR_REGISTRATION: return createValidatorRegistrationRequest(); + case BLOB_SIDECAR: + return createBlobSidecarRequest(); default: throw new IllegalStateException("Unknown eth2 signing type"); } @@ -144,24 +148,12 @@ private static Eth2SigningRequestBody createAggregateAndProof() { final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForSignAggregateAndProof( aggregateAndProof.asInternalAggregateAndProof(SPEC), forkInfo.asInternalForkInfo()); - - return new Eth2SigningRequestBody( - ArtifactType.AGGREGATE_AND_PROOF, - signingRoot, - forkInfo, - null, - null, - null, - null, - aggregateAndProof, - null, - null, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.AGGREGATE_AND_PROOF) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withAggregateAndProof(aggregateAndProof) + .build(); } private static Eth2SigningRequestBody createAggregationSlot() { @@ -170,23 +162,13 @@ private static Eth2SigningRequestBody createAggregationSlot() { final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForSignAggregationSlot( aggregationSlot.getSlot(), forkInfo.asInternalForkInfo()); - return new Eth2SigningRequestBody( - ArtifactType.AGGREGATION_SLOT, - signingRoot, - forkInfo, - null, - null, - null, - aggregationSlot, - null, - null, - null, - null, - null, - null, - null, - null, - null); + + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.AGGREGATION_SLOT) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withAggregationSlot(aggregationSlot) + .build(); } private static Eth2SigningRequestBody createAttestationRequest() { @@ -199,23 +181,12 @@ private static Eth2SigningRequestBody createRandaoReveal() { final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForRandaoReveal( randaoReveal.getEpoch(), forkInfo.asInternalForkInfo()); - return new Eth2SigningRequestBody( - ArtifactType.RANDAO_REVEAL, - signingRoot, - forkInfo, - null, - null, - null, - null, - null, - null, - randaoReveal, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.RANDAO_REVEAL) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withRandaoReveal(randaoReveal) + .build(); } private static Eth2SigningRequestBody createVoluntaryExit() { @@ -224,23 +195,12 @@ private static Eth2SigningRequestBody createVoluntaryExit() { final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForSignVoluntaryExit( voluntaryExit.asInternalVoluntaryExit(), forkInfo.asInternalForkInfo()); - return new Eth2SigningRequestBody( - ArtifactType.VOLUNTARY_EXIT, - signingRoot, - forkInfo, - null, - null, - null, - null, - null, - voluntaryExit, - null, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.VOLUNTARY_EXIT) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withVoluntaryExit(voluntaryExit) + .build(); } private static Eth2SigningRequestBody createDepositRequest() { @@ -255,23 +215,11 @@ private static Eth2SigningRequestBody createDepositRequest() { final Bytes signingRoot = DepositSigningRootUtil.computeSigningRoot( depositMessage.asInternalDepositMessage(), depositDomain); - return new Eth2SigningRequestBody( - ArtifactType.DEPOSIT, - signingRoot, - null, - null, - null, - null, - null, - null, - null, - null, - depositMessage, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.DEPOSIT) + .withSigningRoot(signingRoot) + .withDeposit(depositMessage) + .build(); } public static Eth2SigningRequestBody createAttestationRequest( @@ -291,23 +239,12 @@ public static Eth2SigningRequestBody createAttestationRequest( final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForSignAttestationData( attestationData.asInternalAttestationData(), forkInfo.asInternalForkInfo()); - return new Eth2SigningRequestBody( - ArtifactType.ATTESTATION, - signingRoot, - forkInfo, - null, - null, - attestationData, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.ATTESTATION) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withAttestation(attestationData) + .build(); } public static Eth2SigningRequestBody createBlockRequest() { @@ -344,23 +281,12 @@ public static Eth2SigningRequestBody createBlockRequest( final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForSignBlock( block.asInternalBeaconBlock(SPEC), forkInfo.asInternalForkInfo()); - return new Eth2SigningRequestBody( - ArtifactType.BLOCK, - signingRoot, - forkInfo, - block, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.BLOCK) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withBlock(block) + .build(); } public static ForkInfo forkInfo() { @@ -402,24 +328,12 @@ private static Eth2SigningRequestBody createSyncCommitteeMessageRequest() { final SyncCommitteeMessage syncCommitteeMessage = new SyncCommitteeMessage(BEACON_BLOCK_ROOT, SLOT); - - return new Eth2SigningRequestBody( - ArtifactType.SYNC_COMMITTEE_MESSAGE, - signingRoot, - forkInfo, - null, - null, - null, - null, - null, - null, - null, - null, - syncCommitteeMessage, - null, - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.SYNC_COMMITTEE_MESSAGE) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withSyncCommitteeMessage(syncCommitteeMessage) + .build(); } private static Eth2SigningRequestBody createSyncCommitteeSelectionProofRequest() { @@ -441,23 +355,12 @@ private static Eth2SigningRequestBody createSyncCommitteeSelectionProofRequest() throw new RuntimeException(e); } - return new Eth2SigningRequestBody( - ArtifactType.SYNC_COMMITTEE_SELECTION_PROOF, - signingRoot, - forkInfo, - null, - null, - null, - null, - null, - null, - null, - null, - null, - getSyncAggregatorSelectionData(SLOT, subcommitteeIndex), - null, - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.SYNC_COMMITTEE_SELECTION_PROOF) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withSyncAggregatorSelectionData(getSyncAggregatorSelectionData(SLOT, subcommitteeIndex)) + .build(); } private static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2 @@ -482,23 +385,12 @@ private static Eth2SigningRequestBody createSyncCommitteeContributionAndProofReq throw new RuntimeException(e); } - return new Eth2SigningRequestBody( - ArtifactType.SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF, - signingRoot, - forkInfo, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - getContributionAndProof(), - null, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withContributionAndProof(getContributionAndProof()) + .build(); } private static Eth2SigningRequestBody createValidatorRegistrationRequest() { @@ -511,23 +403,11 @@ private static Eth2SigningRequestBody createValidatorRegistrationRequest() { final Bytes signingRoot = SIGNING_ROOT_UTIL.signingRootForValidatorRegistration( validatorRegistration.asInternalValidatorRegistration()); - return new Eth2SigningRequestBody( - ArtifactType.VALIDATOR_REGISTRATION, - signingRoot, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - validatorRegistration, - null); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.VALIDATOR_REGISTRATION) + .withSigningRoot(signingRoot) + .withValidatorRegistration(validatorRegistration) + .build(); } private static tech.pegasys.teku.api.schema.altair.ContributionAndProof @@ -544,4 +424,25 @@ private static SafeFuture signingRootFromSyncCommitteeUtils( return SafeFuture.of( () -> createSigningRoot.apply(ALTAIR_SPEC.getSyncCommitteeUtilRequired(slot))); } + + private static Eth2SigningRequestBody createBlobSidecarRequest() { + final Spec spec = TestSpecFactory.createMinimal(SpecMilestone.DENEB); + final tech.pegasys.teku.spec.datastructures.state.ForkInfo tekuForkInfo = + Eth2RequestUtils.forkInfo().asInternalForkInfo(); + final Fork tekuFork = new Fork(tekuForkInfo.getFork()); + final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo forkInfo = + new tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo( + tekuFork, tekuForkInfo.getGenesisValidatorsRoot()); + final BlindedBlobSidecar tekuBlindedBlobSidecar = + new DataStructureUtil(spec).randomBlindedBlobSidecar(); + final Bytes signingRoot = + new SigningRootUtil(spec) + .signingRootForBlindedBlobSidecar(tekuBlindedBlobSidecar, tekuForkInfo); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.BLOB_SIDECAR) + .withSigningRoot(signingRoot) + .withForkInfo(forkInfo) + .withBlindedBlobSidecar(fromInternalBlindedBlobSidecar(tekuBlindedBlobSidecar)) + .build(); + } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java new file mode 100644 index 000000000..301915380 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java @@ -0,0 +1,162 @@ +/* + * Copyright 2023 ConsenSys AG. + * + * 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.web3signer.dsl.utils; + +import tech.pegasys.teku.api.schema.AggregateAndProof; +import tech.pegasys.teku.api.schema.AttestationData; +import tech.pegasys.teku.api.schema.BeaconBlock; +import tech.pegasys.teku.api.schema.VoluntaryExit; +import tech.pegasys.teku.api.schema.altair.ContributionAndProof; +import tech.pegasys.web3signer.core.service.http.ArtifactType; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.AggregationSlot; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlockRequest; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.DepositMessage; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.RandaoReveal; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.SyncAggregatorSelectionData; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.SyncCommitteeMessage; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ValidatorRegistration; + +import org.apache.tuweni.bytes.Bytes; + +public final class Eth2SigningRequestBodyBuilder { + private ArtifactType type; + private Bytes signingRoot; + private ForkInfo forkInfo; + private BeaconBlock block; + private BlockRequest blockRequest; + private AttestationData attestation; + private AggregationSlot aggregationSlot; + private AggregateAndProof aggregateAndProof; + private VoluntaryExit voluntaryExit; + private RandaoReveal randaoReveal; + private DepositMessage deposit; + private SyncCommitteeMessage syncCommitteeMessage; + private SyncAggregatorSelectionData syncAggregatorSelectionData; + private ContributionAndProof contributionAndProof; + private ValidatorRegistration validatorRegistration; + private BlindedBlobSidecar blindedBlobSidecar; + + private Eth2SigningRequestBodyBuilder() {} + + public static Eth2SigningRequestBodyBuilder anEth2SigningRequestBody() { + return new Eth2SigningRequestBodyBuilder(); + } + + public Eth2SigningRequestBodyBuilder withType(ArtifactType type) { + this.type = type; + return this; + } + + public Eth2SigningRequestBodyBuilder withSigningRoot(Bytes signingRoot) { + this.signingRoot = signingRoot; + return this; + } + + public Eth2SigningRequestBodyBuilder withForkInfo(ForkInfo forkInfo) { + this.forkInfo = forkInfo; + return this; + } + + public Eth2SigningRequestBodyBuilder withBlock(BeaconBlock block) { + this.block = block; + return this; + } + + public Eth2SigningRequestBodyBuilder withBlockRequest(BlockRequest blockRequest) { + this.blockRequest = blockRequest; + return this; + } + + public Eth2SigningRequestBodyBuilder withAttestation(AttestationData attestation) { + this.attestation = attestation; + return this; + } + + public Eth2SigningRequestBodyBuilder withAggregationSlot(AggregationSlot aggregationSlot) { + this.aggregationSlot = aggregationSlot; + return this; + } + + public Eth2SigningRequestBodyBuilder withAggregateAndProof(AggregateAndProof aggregateAndProof) { + this.aggregateAndProof = aggregateAndProof; + return this; + } + + public Eth2SigningRequestBodyBuilder withVoluntaryExit(VoluntaryExit voluntaryExit) { + this.voluntaryExit = voluntaryExit; + return this; + } + + public Eth2SigningRequestBodyBuilder withRandaoReveal(RandaoReveal randaoReveal) { + this.randaoReveal = randaoReveal; + return this; + } + + public Eth2SigningRequestBodyBuilder withDeposit(DepositMessage deposit) { + this.deposit = deposit; + return this; + } + + public Eth2SigningRequestBodyBuilder withSyncCommitteeMessage( + SyncCommitteeMessage syncCommitteeMessage) { + this.syncCommitteeMessage = syncCommitteeMessage; + return this; + } + + public Eth2SigningRequestBodyBuilder withSyncAggregatorSelectionData( + SyncAggregatorSelectionData syncAggregatorSelectionData) { + this.syncAggregatorSelectionData = syncAggregatorSelectionData; + return this; + } + + public Eth2SigningRequestBodyBuilder withContributionAndProof( + ContributionAndProof contributionAndProof) { + this.contributionAndProof = contributionAndProof; + return this; + } + + public Eth2SigningRequestBodyBuilder withValidatorRegistration( + ValidatorRegistration validatorRegistration) { + this.validatorRegistration = validatorRegistration; + return this; + } + + public Eth2SigningRequestBodyBuilder withBlindedBlobSidecar( + BlindedBlobSidecar blindedBlobSidecar) { + this.blindedBlobSidecar = blindedBlobSidecar; + return this; + } + + public Eth2SigningRequestBody build() { + return new Eth2SigningRequestBody( + type, + signingRoot, + forkInfo, + block, + blockRequest, + attestation, + aggregationSlot, + aggregateAndProof, + voluntaryExit, + randaoReveal, + deposit, + syncCommitteeMessage, + syncAggregatorSelectionData, + contributionAndProof, + validatorRegistration, + blindedBlobSidecar); + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java index 0573e4cd2..2f9ee969a 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/Eth2DepositSigningAcceptanceTest.java @@ -24,6 +24,7 @@ import tech.pegasys.web3signer.core.service.http.ArtifactType; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.DepositMessage; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody; +import tech.pegasys.web3signer.dsl.utils.Eth2SigningRequestBodyBuilder; import tech.pegasys.web3signer.dsl.utils.MetadataFileHelpers; import java.io.IOException; @@ -102,23 +103,10 @@ private void verifyDepositData(final Map depositData) throws IOE UInt64.valueOf(depositData.get("amount")), Bytes4.fromHexString(depositData.get("fork_version"))); final Eth2SigningRequestBody requestBody = - new Eth2SigningRequestBody( - ArtifactType.DEPOSIT, - null, - null, - null, - null, - null, - null, - null, - null, - null, - depositMessage, - null, - null, - null, - null, - null); + Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() + .withType(ArtifactType.DEPOSIT) + .withDeposit(depositMessage) + .build(); final Response response = signer.eth2Sign(publicKey, requestBody, TEXT); From f90a6e1b0a1c8579e4df0ceb7efe7bdb46827151 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 23 Aug 2023 23:35:06 +1000 Subject: [PATCH 04/15] setup minimal web3signer for blob sidecar --- .../tests/signing/BlsSigningAcceptanceTest.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java index add73e0db..674c7d767 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java @@ -343,15 +343,10 @@ private void signAndVerifySignature( private void setupMinimalWeb3Signer(final ArtifactType artifactType) { switch (artifactType) { - case BLOCK_V2: - case SYNC_COMMITTEE_MESSAGE: - case SYNC_COMMITTEE_SELECTION_PROOF: - case SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF: - setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.ALTAIR); - break; - default: - setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.PHASE0); - break; + case BLOCK_V2, SYNC_COMMITTEE_MESSAGE, SYNC_COMMITTEE_SELECTION_PROOF, SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF -> setupEth2Signer( + Eth2Network.MINIMAL, SpecMilestone.ALTAIR); + case BLOB_SIDECAR -> setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.DENEB); + default -> setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.PHASE0); } } From b012e49167fec8d4400a1508fd197b63301687e9 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Thu, 24 Aug 2023 00:05:21 +1000 Subject: [PATCH 05/15] AT for Blobsidecar and BlindedBlobSidecar --- .../dsl/utils/Eth2RequestUtils.java | 29 +++++-- ...lsBlindedBlobcarSigningAcceptanceTest.java | 75 +++++++++++++++++++ 2 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java index d9c109d9f..007800f02 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java @@ -14,6 +14,7 @@ import static java.util.Collections.emptyList; import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar.fromInternalBlindedBlobSidecar; +import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar.fromInternalBlobSidecar; import static tech.pegasys.web3signer.core.util.DepositSigningRootUtil.computeDomain; import tech.pegasys.teku.api.schema.AggregateAndProof; @@ -35,6 +36,7 @@ import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.constants.Domain; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar; +import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.ContributionAndProof; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncAggregatorSelectionData; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncCommitteeContribution; @@ -116,7 +118,7 @@ public static Eth2SigningRequestBody createCannedRequest(final ArtifactType arti case VALIDATOR_REGISTRATION: return createValidatorRegistrationRequest(); case BLOB_SIDECAR: - return createBlobSidecarRequest(); + return createBlobSidecarRequest(false); default: throw new IllegalStateException("Unknown eth2 signing type"); } @@ -425,7 +427,7 @@ private static SafeFuture signingRootFromSyncCommitteeUtils( () -> createSigningRoot.apply(ALTAIR_SPEC.getSyncCommitteeUtilRequired(slot))); } - private static Eth2SigningRequestBody createBlobSidecarRequest() { + public static Eth2SigningRequestBody createBlobSidecarRequest(final boolean isBlinded) { final Spec spec = TestSpecFactory.createMinimal(SpecMilestone.DENEB); final tech.pegasys.teku.spec.datastructures.state.ForkInfo tekuForkInfo = Eth2RequestUtils.forkInfo().asInternalForkInfo(); @@ -433,16 +435,27 @@ private static Eth2SigningRequestBody createBlobSidecarRequest() { final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo forkInfo = new tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo( tekuFork, tekuForkInfo.getGenesisValidatorsRoot()); - final BlindedBlobSidecar tekuBlindedBlobSidecar = - new DataStructureUtil(spec).randomBlindedBlobSidecar(); - final Bytes signingRoot = - new SigningRootUtil(spec) - .signingRootForBlindedBlobSidecar(tekuBlindedBlobSidecar, tekuForkInfo); + final Bytes signingRoot; + final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar + blindedBlobSidecar; + if (isBlinded) { + final BlindedBlobSidecar tekuBlindedBlobSidecar = + new DataStructureUtil(spec).randomBlindedBlobSidecar(); + signingRoot = + new SigningRootUtil(spec) + .signingRootForBlindedBlobSidecar(tekuBlindedBlobSidecar, tekuForkInfo); + blindedBlobSidecar = fromInternalBlindedBlobSidecar(tekuBlindedBlobSidecar); + } else { + final BlobSidecar tekuBlobSidecar = new DataStructureUtil(spec).randomBlobSidecar(); + signingRoot = + new SigningRootUtil(spec).signingRootForBlobSidecar(tekuBlobSidecar, tekuForkInfo); + blindedBlobSidecar = fromInternalBlobSidecar(tekuBlobSidecar); + } return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() .withType(ArtifactType.BLOB_SIDECAR) .withSigningRoot(signingRoot) .withForkInfo(forkInfo) - .withBlindedBlobSidecar(fromInternalBlindedBlobSidecar(tekuBlindedBlobSidecar)) + .withBlindedBlobSidecar(blindedBlobSidecar) .build(); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java new file mode 100644 index 000000000..61ee8b744 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2020 ConsenSys AG. + * + * 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.web3signer.tests.signing; + +import static io.restassured.http.ContentType.JSON; +import static org.assertj.core.api.Assertions.assertThat; + +import tech.pegasys.teku.bls.BLS; +import tech.pegasys.teku.bls.BLSKeyPair; +import tech.pegasys.teku.bls.BLSPublicKey; +import tech.pegasys.teku.bls.BLSSecretKey; +import tech.pegasys.teku.bls.BLSSignature; +import tech.pegasys.teku.spec.SpecMilestone; +import tech.pegasys.teku.spec.networks.Eth2Network; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody; +import tech.pegasys.web3signer.dsl.utils.Eth2RequestUtils; +import tech.pegasys.web3signer.dsl.utils.MetadataFileHelpers; +import tech.pegasys.web3signer.signing.KeyType; + +import java.nio.file.Path; + +import com.fasterxml.jackson.core.JsonProcessingException; +import io.restassured.http.ContentType; +import io.restassured.response.Response; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class BlsBlindedBlobcarSigningAcceptanceTest extends SigningAcceptanceTestBase { + + private static final String PRIVATE_KEY = + "3ee2224386c82ffea477e2adf28a2929f5c349165a4196158c7f3a2ecca40f35"; + private static final MetadataFileHelpers METADATA_FILE_HELPERS = new MetadataFileHelpers(); + private static final BLSSecretKey KEY = + BLSSecretKey.fromBytes(Bytes32.fromHexString(PRIVATE_KEY)); + private static final BLSKeyPair KEY_PAIR = new BLSKeyPair(KEY); + private static final BLSPublicKey PUBLIC_KEY = KEY_PAIR.getPublicKey(); + + @ParameterizedTest(name = "#{index} - Blinded Blobsidecar Signing: {0}") + @ValueSource(booleans = {true, false}) + public void signBlobSidecarAndBlindedBlobSidecar(final boolean isBlinded) + throws JsonProcessingException { + final String configFilename = PUBLIC_KEY.toString().substring(2); + final Path keyConfigFile = testDirectory.resolve(configFilename + ".yaml"); + METADATA_FILE_HELPERS.createUnencryptedYamlFileAt(keyConfigFile, PRIVATE_KEY, KeyType.BLS); + + signAndVerifySignature(isBlinded); + } + + private void signAndVerifySignature(final boolean isBlinded) throws JsonProcessingException { + final ContentType acceptMediaType = JSON; + setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.DENEB); + + // openapi + final Eth2SigningRequestBody request = Eth2RequestUtils.createBlobSidecarRequest(isBlinded); + + // send modified JSON containing signing_root or signingRoot + final Response response = + signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, acceptMediaType); + final Bytes signature = verifyAndGetSignatureResponse(response, acceptMediaType); + final BLSSignature expectedSignature = BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()); + assertThat(signature).isEqualTo(expectedSignature.toBytesCompressed()); + } +} From 2ddc2bd1a3594c266fcb7bd01c38922f17da63e3 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Thu, 24 Aug 2023 00:08:00 +1000 Subject: [PATCH 06/15] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba20859ca..9ed2ea2fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### Breaking Changes - Eth2 Signing request body: deprecating `signingRoot` in favor of `signing_root` property. `signingRoot` will be removed in a future release. +### Features Added +- Signing support for BlobSidecar and BlindedBlobsidecar in Deneb fork. + ## 23.8.1 ### Bugs fixed From 6356aeca6700eecb8253348dc38b35659ff0e175 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Thu, 24 Aug 2023 00:11:26 +1000 Subject: [PATCH 07/15] remove unnecessary comment --- .../tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java index 61ee8b744..d836aeada 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java @@ -62,10 +62,8 @@ private void signAndVerifySignature(final boolean isBlinded) throws JsonProcessi final ContentType acceptMediaType = JSON; setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.DENEB); - // openapi final Eth2SigningRequestBody request = Eth2RequestUtils.createBlobSidecarRequest(isBlinded); - // send modified JSON containing signing_root or signingRoot final Response response = signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, acceptMediaType); final Bytes signature = verifyAndGetSignatureResponse(response, acceptMediaType); From 44506fe7bc1409f6140ceb6b0c989dc898456be4 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Fri, 25 Aug 2023 15:38:11 +1000 Subject: [PATCH 08/15] Convert W3S BlindedBlobSidecar to BlobSidecar --- .../dsl/utils/Eth2RequestUtils.java | 15 ++--- .../utils/Eth2SigningRequestBodyBuilder.java | 11 ++-- .../signing/BlsSigningAcceptanceTest.java | 4 +- ...indedBlobSidecar.java => BlobSidecar.java} | 61 ++++++++++++------- .../eth2/Eth2SignForIdentifierHandler.java | 7 +-- .../signing/eth2/Eth2SigningRequestBody.java | 2 +- 6 files changed, 58 insertions(+), 42 deletions(-) rename core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/{BlindedBlobSidecar.java => BlobSidecar.java} (76%) diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java index 007800f02..4726716bb 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java @@ -13,8 +13,8 @@ package tech.pegasys.web3signer.dsl.utils; import static java.util.Collections.emptyList; -import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar.fromInternalBlindedBlobSidecar; -import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar.fromInternalBlobSidecar; +import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar.fromInternalBlindedBlobSidecar; +import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar.fromInternalBlobSidecar; import static tech.pegasys.web3signer.core.util.DepositSigningRootUtil.computeDomain; import tech.pegasys.teku.api.schema.AggregateAndProof; @@ -436,26 +436,27 @@ public static Eth2SigningRequestBody createBlobSidecarRequest(final boolean isBl new tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo( tekuFork, tekuForkInfo.getGenesisValidatorsRoot()); final Bytes signingRoot; - final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar - blindedBlobSidecar; + final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar blobSidecar; if (isBlinded) { + // generate random blinded blobsidecar final BlindedBlobSidecar tekuBlindedBlobSidecar = new DataStructureUtil(spec).randomBlindedBlobSidecar(); signingRoot = new SigningRootUtil(spec) .signingRootForBlindedBlobSidecar(tekuBlindedBlobSidecar, tekuForkInfo); - blindedBlobSidecar = fromInternalBlindedBlobSidecar(tekuBlindedBlobSidecar); + blobSidecar = fromInternalBlindedBlobSidecar(tekuBlindedBlobSidecar); } else { + // generate random blobsidecar final BlobSidecar tekuBlobSidecar = new DataStructureUtil(spec).randomBlobSidecar(); signingRoot = new SigningRootUtil(spec).signingRootForBlobSidecar(tekuBlobSidecar, tekuForkInfo); - blindedBlobSidecar = fromInternalBlobSidecar(tekuBlobSidecar); + blobSidecar = fromInternalBlobSidecar(tekuBlobSidecar); } return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() .withType(ArtifactType.BLOB_SIDECAR) .withSigningRoot(signingRoot) .withForkInfo(forkInfo) - .withBlindedBlobSidecar(blindedBlobSidecar) + .withBlobSidecar(blobSidecar) .build(); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java index 301915380..7c86c2703 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2SigningRequestBodyBuilder.java @@ -19,7 +19,7 @@ import tech.pegasys.teku.api.schema.altair.ContributionAndProof; import tech.pegasys.web3signer.core.service.http.ArtifactType; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.AggregationSlot; -import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlindedBlobSidecar; +import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlockRequest; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.DepositMessage; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody; @@ -47,7 +47,7 @@ public final class Eth2SigningRequestBodyBuilder { private SyncAggregatorSelectionData syncAggregatorSelectionData; private ContributionAndProof contributionAndProof; private ValidatorRegistration validatorRegistration; - private BlindedBlobSidecar blindedBlobSidecar; + private BlobSidecar blobSidecar; private Eth2SigningRequestBodyBuilder() {} @@ -134,9 +134,8 @@ public Eth2SigningRequestBodyBuilder withValidatorRegistration( return this; } - public Eth2SigningRequestBodyBuilder withBlindedBlobSidecar( - BlindedBlobSidecar blindedBlobSidecar) { - this.blindedBlobSidecar = blindedBlobSidecar; + public Eth2SigningRequestBodyBuilder withBlobSidecar(BlobSidecar blobSidecar) { + this.blobSidecar = blobSidecar; return this; } @@ -157,6 +156,6 @@ public Eth2SigningRequestBody build() { syncAggregatorSelectionData, contributionAndProof, validatorRegistration, - blindedBlobSidecar); + blobSidecar); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java index 674c7d767..5bcf5ad60 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java @@ -261,7 +261,7 @@ public void failsIfSigningRootDoesNotMatchSigningData(final ArtifactType artifac request.syncAggregatorSelectionData(), request.contributionAndProof(), request.validatorRegistration(), - request.blindedBlobSidecar()); + request.blobSidecar()); final Response response = signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), requestWithMismatchedSigningRoot); @@ -300,7 +300,7 @@ public void ableToSignWithoutSigningRootField(final ContentType acceptableConten request.syncAggregatorSelectionData(), request.contributionAndProof(), request.validatorRegistration(), - request.blindedBlobSidecar()); + request.blobSidecar()); final Response response = signer.eth2Sign( diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java similarity index 76% rename from core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java rename to core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java index 97e0716ef..c01b664fb 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlindedBlobSidecar.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java @@ -16,12 +16,25 @@ import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.SpecVersion; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecarSchema; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.annotations.VisibleForTesting; import org.apache.tuweni.bytes.Bytes32; -public record BlindedBlobSidecar( +/** + * Json representation of BlindedBlobSidecar and BlobSidecar. The blob_root is the "hash tree root" + * of BlobSidecar's blob + * + * @param blockRoot Block root + * @param index Index + * @param slot Slot + * @param blockParentRoot Block Parent Root + * @param proposerIndex Proposer Index + * @param blobRoot Blob Root. + * @param kzgCommitment KZG Commitment + * @param kzgProof KZG Proof + */ +public record BlobSidecar( @JsonProperty("block_root") Bytes32 blockRoot, @JsonProperty("index") UInt64 index, @JsonProperty("slot") UInt64 slot, @@ -31,9 +44,26 @@ public record BlindedBlobSidecar( @JsonProperty("kzg_commitment") KZGCommitment kzgCommitment, @JsonProperty("kzg_proof") KZGProof kzgProof) { - public static BlindedBlobSidecar fromInternalBlindedBlobSidecar( + public tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar + asInternalBlindedBlobSidecar(final SpecVersion spec) { + final BlindedBlobSidecarSchema blindedBlobSidecarSchema = + spec.getSchemaDefinitions().toVersionDeneb().orElseThrow().getBlindedBlobSidecarSchema(); + return new tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar( + blindedBlobSidecarSchema, + blockRoot, + index, + slot, + blockParentRoot, + proposerIndex, + blobRoot, + kzgCommitment.asInternalKZGCommitment(), + kzgProof.asInternalKZGProof()); + } + + @VisibleForTesting + public static BlobSidecar fromInternalBlindedBlobSidecar( tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar sidecar) { - return new BlindedBlobSidecar( + return new BlobSidecar( sidecar.getBlockRoot(), sidecar.getIndex(), sidecar.getSlot(), @@ -44,31 +74,18 @@ public static BlindedBlobSidecar fromInternalBlindedBlobSidecar( new KZGProof(sidecar.getKZGProof())); } - public static BlindedBlobSidecar fromInternalBlobSidecar(final BlobSidecar sidecar) { - return new BlindedBlobSidecar( + @VisibleForTesting + public static BlobSidecar fromInternalBlobSidecar( + final tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar sidecar) { + return new BlobSidecar( sidecar.getBlockRoot(), sidecar.getIndex(), sidecar.getSlot(), sidecar.getBlockParentRoot(), sidecar.getProposerIndex(), + // convert blob to hash tree root to make it assignable to W3S BlobSidecar sidecar.getBlob().hashTreeRoot(), new KZGCommitment(sidecar.getKZGCommitment()), new KZGProof(sidecar.getKZGProof())); } - - public tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar - asInternalBlindedBlobSidecar(final SpecVersion spec) { - final BlindedBlobSidecarSchema blindedBlobSidecarSchema = - spec.getSchemaDefinitions().toVersionDeneb().orElseThrow().getBlindedBlobSidecarSchema(); - return new tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar( - blindedBlobSidecarSchema, - blockRoot, - index, - slot, - blockParentRoot, - proposerIndex, - blobRoot, - kzgCommitment.asInternalKZGCommitment(), - kzgProof.asInternalKZGProof()); - } } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java index 230f1b344..15a64f7de 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SignForIdentifierHandler.java @@ -319,11 +319,10 @@ private Bytes computeSigningRoot(final Eth2SigningRequestBody body) { validatorRegistration.asInternalValidatorRegistration()); case BLOB_SIDECAR: // handles both blinded/blob sidecar - final BlindedBlobSidecar blindedBlobSidecar = body.blindedBlobSidecar(); - checkArgument(blindedBlobSidecar != null, "BlobSidecar is required"); + final BlobSidecar blobSidecar = body.blobSidecar(); + checkArgument(blobSidecar != null, "BlobSidecar is required"); return signingRootUtil.signingRootForBlindedBlobSidecar( - blindedBlobSidecar.asInternalBlindedBlobSidecar( - eth2Spec.atSlot(blindedBlobSidecar.slot())), + blobSidecar.asInternalBlindedBlobSidecar(eth2Spec.atSlot(blobSidecar.slot())), body.forkInfo().asInternalForkInfo()); default: diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java index ef7be492f..256946287 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/Eth2SigningRequestBody.java @@ -40,4 +40,4 @@ public record Eth2SigningRequestBody( SyncAggregatorSelectionData syncAggregatorSelectionData, @JsonProperty("contribution_and_proof") ContributionAndProof contributionAndProof, @JsonProperty("validator_registration") ValidatorRegistration validatorRegistration, - @JsonProperty("blob_sidecar") BlindedBlobSidecar blindedBlobSidecar) {} + @JsonProperty("blob_sidecar") BlobSidecar blobSidecar) {} From a7b2492090fba0b34e789b4abb60fcf106439495 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Fri, 25 Aug 2023 15:39:59 +1000 Subject: [PATCH 09/15] fixing year in license header --- .../tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java | 2 +- .../core/service/http/handlers/signing/eth2/KZGProof.java | 2 +- .../http/handlers/signing/eth2/json/KZGProofDeserializer.java | 2 +- .../http/handlers/signing/eth2/json/KZGProofSerializer.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java index d836aeada..57816fa2d 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 ConsenSys AG. + * Copyright 2023 ConsenSys AG. * * 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 diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java index c7c11f8e1..b6470c06c 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/KZGProof.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 ConsenSys AG. + * Copyright 2023 ConsenSys AG. * * 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 diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java index 089f926ec..74e21dcb4 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 ConsenSys AG. + * Copyright 2023 ConsenSys AG. * * 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 diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java index 5849c28fd..e212f2d79 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/json/KZGProofSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 ConsenSys AG. + * Copyright 2023 ConsenSys AG. * * 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 From 8a9e9805e0dad5bec55b9e94f14988f79f138e83 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Fri, 25 Aug 2023 15:47:24 +1000 Subject: [PATCH 10/15] Updating PG JDBC driver due to CVE --- gradle/versions.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/versions.gradle b/gradle/versions.gradle index d4bb79858..d9a7513e2 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -134,7 +134,7 @@ dependencyManagement { dependency 'com.azure:azure-core-http-netty:1.13.5' dependency 'com.zaxxer:HikariCP:5.0.1' - dependency 'org.postgresql:postgresql:42.5.3' + dependency 'org.postgresql:postgresql:42.6.0' dependencySet(group: 'org.jdbi', version: '3.36.0') { entry 'jdbi3-core' From 3b55dc788ece9f627461409c684c0a785a9b36fc Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Mon, 28 Aug 2023 11:09:30 +1000 Subject: [PATCH 11/15] Trigger Build From ca4008016efa6fd0afd0c898eccd9a5019a3d51f Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Mon, 28 Aug 2023 14:51:56 +1000 Subject: [PATCH 12/15] Refactoring after review --- CHANGELOG.md | 2 +- ...anceTest.java => BlsBlobSidecarSigningAcceptanceTest.java} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/{BlsBlindedBlobcarSigningAcceptanceTest.java => BlsBlobSidecarSigningAcceptanceTest.java} (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ed2ea2fe..901e9c69d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - Eth2 Signing request body: deprecating `signingRoot` in favor of `signing_root` property. `signingRoot` will be removed in a future release. ### Features Added -- Signing support for BlobSidecar and BlindedBlobsidecar in Deneb fork. +- Signing support for BlobSidecar and BlindedBlobSidecar in Deneb fork. ## 23.8.1 diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java similarity index 95% rename from acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java rename to acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java index 57816fa2d..8d53851a8 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlindedBlobcarSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java @@ -37,7 +37,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -public class BlsBlindedBlobcarSigningAcceptanceTest extends SigningAcceptanceTestBase { +public class BlsBlobSidecarSigningAcceptanceTest extends SigningAcceptanceTestBase { private static final String PRIVATE_KEY = "3ee2224386c82ffea477e2adf28a2929f5c349165a4196158c7f3a2ecca40f35"; @@ -47,7 +47,7 @@ public class BlsBlindedBlobcarSigningAcceptanceTest extends SigningAcceptanceTes private static final BLSKeyPair KEY_PAIR = new BLSKeyPair(KEY); private static final BLSPublicKey PUBLIC_KEY = KEY_PAIR.getPublicKey(); - @ParameterizedTest(name = "#{index} - Blinded Blobsidecar Signing: {0}") + @ParameterizedTest(name = "#{index} - BlobSidecar Signing: (Is blinded: {0})") @ValueSource(booleans = {true, false}) public void signBlobSidecarAndBlindedBlobSidecar(final boolean isBlinded) throws JsonProcessingException { From 91fa00a15c150968f171fba35d732943a77e926c Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Mon, 28 Aug 2023 14:55:41 +1000 Subject: [PATCH 13/15] remove @param from javadoc --- .../service/http/handlers/signing/eth2/BlobSidecar.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java index c01b664fb..882bddf3a 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java @@ -24,15 +24,6 @@ /** * Json representation of BlindedBlobSidecar and BlobSidecar. The blob_root is the "hash tree root" * of BlobSidecar's blob - * - * @param blockRoot Block root - * @param index Index - * @param slot Slot - * @param blockParentRoot Block Parent Root - * @param proposerIndex Proposer Index - * @param blobRoot Blob Root. - * @param kzgCommitment KZG Commitment - * @param kzgProof KZG Proof */ public record BlobSidecar( @JsonProperty("block_root") Bytes32 blockRoot, From c8f8398cfff6542b83f8a85185a0af2822fb91dc Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 30 Aug 2023 20:39:43 +1000 Subject: [PATCH 14/15] Review suggestion - remove blinded blob sidecar acceptance test --- .../dsl/utils/Eth2RequestUtils.java | 30 ++++++------------ .../BlsBlobSidecarSigningAcceptanceTest.java | 31 ++++++++----------- .../handlers/signing/eth2/BlobSidecar.java | 14 --------- 3 files changed, 22 insertions(+), 53 deletions(-) diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java index 4726716bb..f2e44ca2b 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java @@ -13,7 +13,6 @@ package tech.pegasys.web3signer.dsl.utils; import static java.util.Collections.emptyList; -import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar.fromInternalBlindedBlobSidecar; import static tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar.fromInternalBlobSidecar; import static tech.pegasys.web3signer.core.util.DepositSigningRootUtil.computeDomain; @@ -35,7 +34,6 @@ import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecFactory; import tech.pegasys.teku.spec.constants.Domain; -import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar; import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.ContributionAndProof; import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncAggregatorSelectionData; @@ -118,7 +116,7 @@ public static Eth2SigningRequestBody createCannedRequest(final ArtifactType arti case VALIDATOR_REGISTRATION: return createValidatorRegistrationRequest(); case BLOB_SIDECAR: - return createBlobSidecarRequest(false); + return createBlobSidecarRequest(); default: throw new IllegalStateException("Unknown eth2 signing type"); } @@ -427,7 +425,7 @@ private static SafeFuture signingRootFromSyncCommitteeUtils( () -> createSigningRoot.apply(ALTAIR_SPEC.getSyncCommitteeUtilRequired(slot))); } - public static Eth2SigningRequestBody createBlobSidecarRequest(final boolean isBlinded) { + public static Eth2SigningRequestBody createBlobSidecarRequest() { final Spec spec = TestSpecFactory.createMinimal(SpecMilestone.DENEB); final tech.pegasys.teku.spec.datastructures.state.ForkInfo tekuForkInfo = Eth2RequestUtils.forkInfo().asInternalForkInfo(); @@ -436,27 +434,17 @@ public static Eth2SigningRequestBody createBlobSidecarRequest(final boolean isBl new tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo( tekuFork, tekuForkInfo.getGenesisValidatorsRoot()); final Bytes signingRoot; - final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlobSidecar blobSidecar; - if (isBlinded) { - // generate random blinded blobsidecar - final BlindedBlobSidecar tekuBlindedBlobSidecar = - new DataStructureUtil(spec).randomBlindedBlobSidecar(); - signingRoot = - new SigningRootUtil(spec) - .signingRootForBlindedBlobSidecar(tekuBlindedBlobSidecar, tekuForkInfo); - blobSidecar = fromInternalBlindedBlobSidecar(tekuBlindedBlobSidecar); - } else { - // generate random blobsidecar - final BlobSidecar tekuBlobSidecar = new DataStructureUtil(spec).randomBlobSidecar(); - signingRoot = - new SigningRootUtil(spec).signingRootForBlobSidecar(tekuBlobSidecar, tekuForkInfo); - blobSidecar = fromInternalBlobSidecar(tekuBlobSidecar); - } + + // generate random blobsidecar + final BlobSidecar tekuBlobSidecar = new DataStructureUtil(spec).randomBlobSidecar(); + signingRoot = + new SigningRootUtil(spec).signingRootForBlobSidecar(tekuBlobSidecar, tekuForkInfo); + return Eth2SigningRequestBodyBuilder.anEth2SigningRequestBody() .withType(ArtifactType.BLOB_SIDECAR) .withSigningRoot(signingRoot) .withForkInfo(forkInfo) - .withBlobSidecar(blobSidecar) + .withBlobSidecar(fromInternalBlobSidecar(tekuBlobSidecar)) .build(); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java index 8d53851a8..fe0a957d3 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsBlobSidecarSigningAcceptanceTest.java @@ -19,7 +19,6 @@ import tech.pegasys.teku.bls.BLSKeyPair; import tech.pegasys.teku.bls.BLSPublicKey; import tech.pegasys.teku.bls.BLSSecretKey; -import tech.pegasys.teku.bls.BLSSignature; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.networks.Eth2Network; import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody; @@ -30,12 +29,11 @@ import java.nio.file.Path; import com.fasterxml.jackson.core.JsonProcessingException; -import io.restassured.http.ContentType; import io.restassured.response.Response; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class BlsBlobSidecarSigningAcceptanceTest extends SigningAcceptanceTestBase { @@ -47,27 +45,24 @@ public class BlsBlobSidecarSigningAcceptanceTest extends SigningAcceptanceTestBa private static final BLSKeyPair KEY_PAIR = new BLSKeyPair(KEY); private static final BLSPublicKey PUBLIC_KEY = KEY_PAIR.getPublicKey(); - @ParameterizedTest(name = "#{index} - BlobSidecar Signing: (Is blinded: {0})") - @ValueSource(booleans = {true, false}) - public void signBlobSidecarAndBlindedBlobSidecar(final boolean isBlinded) - throws JsonProcessingException { + @BeforeEach + void init() { final String configFilename = PUBLIC_KEY.toString().substring(2); final Path keyConfigFile = testDirectory.resolve(configFilename + ".yaml"); METADATA_FILE_HELPERS.createUnencryptedYamlFileAt(keyConfigFile, PRIVATE_KEY, KeyType.BLS); - signAndVerifySignature(isBlinded); + setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.DENEB); } - private void signAndVerifySignature(final boolean isBlinded) throws JsonProcessingException { - final ContentType acceptMediaType = JSON; - setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.DENEB); + @Test + public void signBlobSidecar() throws JsonProcessingException { + final Eth2SigningRequestBody request = Eth2RequestUtils.createBlobSidecarRequest(); - final Eth2SigningRequestBody request = Eth2RequestUtils.createBlobSidecarRequest(isBlinded); + final Response response = signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, JSON); + final Bytes signature = verifyAndGetSignatureResponse(response, JSON); - final Response response = - signer.eth2Sign(KEY_PAIR.getPublicKey().toString(), request, acceptMediaType); - final Bytes signature = verifyAndGetSignatureResponse(response, acceptMediaType); - final BLSSignature expectedSignature = BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()); - assertThat(signature).isEqualTo(expectedSignature.toBytesCompressed()); + final Bytes expectedSignature = + BLS.sign(KEY_PAIR.getSecretKey(), request.signingRoot()).toBytesCompressed(); + assertThat(signature).isEqualTo(expectedSignature); } } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java index 882bddf3a..f6c720893 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/signing/eth2/BlobSidecar.java @@ -51,20 +51,6 @@ public record BlobSidecar( kzgProof.asInternalKZGProof()); } - @VisibleForTesting - public static BlobSidecar fromInternalBlindedBlobSidecar( - tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar sidecar) { - return new BlobSidecar( - sidecar.getBlockRoot(), - sidecar.getIndex(), - sidecar.getSlot(), - sidecar.getBlockParentRoot(), - sidecar.getProposerIndex(), - sidecar.getBlobRoot(), - new KZGCommitment(sidecar.getKZGCommitment()), - new KZGProof(sidecar.getKZGProof())); - } - @VisibleForTesting public static BlobSidecar fromInternalBlobSidecar( final tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar sidecar) { From b5aff5abe69e973dd93089fa42f4ede2963efaba Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 30 Aug 2023 20:42:45 +1000 Subject: [PATCH 15/15] Reverting PG JDBC driver version --- gradle/versions.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/versions.gradle b/gradle/versions.gradle index d9a7513e2..d4bb79858 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -134,7 +134,7 @@ dependencyManagement { dependency 'com.azure:azure-core-http-netty:1.13.5' dependency 'com.zaxxer:HikariCP:5.0.1' - dependency 'org.postgresql:postgresql:42.6.0' + dependency 'org.postgresql:postgresql:42.5.3' dependencySet(group: 'org.jdbi', version: '3.36.0') { entry 'jdbi3-core'