From 21b24211d0e540147307a533c2d9dd9dc0bfc97a Mon Sep 17 00:00:00 2001 From: Stefan Bratanov Date: Tue, 10 Sep 2024 14:38:56 +0300 Subject: [PATCH] try another approach for blind/unblind --- .../v3/validator/GetNewBlockV3Test.java | 9 +- .../teku/api/SchemaObjectProvider.java | 13 +- .../teku/api/schema/SignedBeaconBlock.java | 3 +- .../BlindedBeaconBlockBodyEip7732.java | 143 +++++++++++ .../schema/eip7732/BlindedBlockEip7732.java | 70 ++++++ .../SignedBlindedBeaconBlockEip7732.java | 47 ++++ .../blocks/SignedBeaconBlock.java | 8 +- .../blocks/blockbody/BeaconBlockBody.java | 3 +- .../blockbody/BeaconBlockBodySchema.java | 5 + .../SignedBeaconBlockUnblinderBellatrix.java | 3 +- .../BeaconBlockBodyBuilderEip7732.java | 28 ++- .../eip7732/BeaconBlockBodyEip7732.java | 5 - .../eip7732/BeaconBlockBodySchemaEip7732.java | 4 - .../BeaconBlockBodySchemaEip7732Impl.java | 2 +- .../BlindedBeaconBlockBodyEip7732.java | 65 +++++ .../BlindedBeaconBlockBodyEip7732Impl.java | 181 ++++++++++++++ .../BlindedBeaconBlockBodySchemaEip7732.java | 31 +++ ...indedBeaconBlockBodySchemaEip7732Impl.java | 232 ++++++++++++++++++ .../schemas/SchemaDefinitionsEip7732.java | 25 +- .../blocks/SignedBeaconBlockTest.java | 14 +- .../teku/spec/util/DataStructureUtil.java | 15 +- .../attestation/PayloadAttestationPool.java | 4 +- 22 files changed, 853 insertions(+), 57 deletions(-) create mode 100644 data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBeaconBlockBodyEip7732.java create mode 100644 data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBlockEip7732.java create mode 100644 data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/SignedBlindedBeaconBlockEip7732.java create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732.java create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732Impl.java create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732.java create mode 100644 ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732Impl.java diff --git a/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3Test.java b/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3Test.java index 521470b6623..1e422952048 100644 --- a/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3Test.java +++ b/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3Test.java @@ -78,15 +78,8 @@ void shouldHandleBlindedBeaconBlocks() throws Exception { assertThat(request.getResponseBody()).isEqualTo(blockContainerAndMetaData); assertThat(request.getResponseHeaders(HEADER_CONSENSUS_VERSION)) .isEqualTo(Version.fromMilestone(blockContainerAndMetaData.specMilestone()).name()); - final boolean expectedHeaderExecutionPayloadBlinded; - if (specMilestone.isGreaterThanOrEqualTo(SpecMilestone.EIP7732)) { - // no blind/unblind concept in ePBS - expectedHeaderExecutionPayloadBlinded = false; - } else { - expectedHeaderExecutionPayloadBlinded = true; - } assertThat(request.getResponseHeaders(HEADER_EXECUTION_PAYLOAD_BLINDED)) - .isEqualTo(Boolean.toString(expectedHeaderExecutionPayloadBlinded)); + .isEqualTo(Boolean.toString(true)); assertThat(request.getResponseHeaders(HEADER_EXECUTION_PAYLOAD_VALUE)) .isEqualTo(blockContainerAndMetaData.executionPayloadValue().toDecimalString()); assertThat(request.getResponseHeaders(HEADER_CONSENSUS_BLOCK_VALUE)) diff --git a/data/provider/src/main/java/tech/pegasys/teku/api/SchemaObjectProvider.java b/data/provider/src/main/java/tech/pegasys/teku/api/SchemaObjectProvider.java index be1a6d481c7..aa6e3a60fa7 100644 --- a/data/provider/src/main/java/tech/pegasys/teku/api/SchemaObjectProvider.java +++ b/data/provider/src/main/java/tech/pegasys/teku/api/SchemaObjectProvider.java @@ -39,6 +39,8 @@ import tech.pegasys.teku.api.schema.eip7732.BeaconBlockBodyEip7732; import tech.pegasys.teku.api.schema.eip7732.BeaconBlockEip7732; import tech.pegasys.teku.api.schema.eip7732.BeaconStateEip7732; +import tech.pegasys.teku.api.schema.eip7732.BlindedBeaconBlockBodyEip7732; +import tech.pegasys.teku.api.schema.eip7732.BlindedBlockEip7732; import tech.pegasys.teku.api.schema.electra.BeaconBlockBodyElectra; import tech.pegasys.teku.api.schema.electra.BeaconBlockElectra; import tech.pegasys.teku.api.schema.electra.BeaconStateElectra; @@ -134,12 +136,12 @@ public BeaconBlock getBlindedBlock( block.getStateRoot(), getBlindedBlockBodyElectra(block.getBody())); case EIP7732 -> - new BeaconBlockEip7732( + new BlindedBlockEip7732( block.getSlot(), block.getProposerIndex(), block.getParentRoot(), block.getStateRoot(), - getBeaconBlockBodyEip7732(block.getBody())); + getBlindedBlockBodyEip7732(block.getBody())); }; } @@ -269,6 +271,13 @@ private BlindedBeaconBlockBodyElectra getBlindedBlockBodyElectra( .BlindedBeaconBlockBodyElectra.required(body)); } + private BlindedBeaconBlockBodyEip7732 getBlindedBlockBodyEip7732( + final tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody body) { + return new BlindedBeaconBlockBodyEip7732( + tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732 + .BlindedBeaconBlockBodyEip7732.required(body)); + } + public BeaconState getBeaconState( final tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState state) { final UInt64 slot = state.getSlot(); diff --git a/data/serializer/src/main/java/tech/pegasys/teku/api/schema/SignedBeaconBlock.java b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/SignedBeaconBlock.java index 8fad83457a1..1986ca9c8ec 100644 --- a/data/serializer/src/main/java/tech/pegasys/teku/api/schema/SignedBeaconBlock.java +++ b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/SignedBeaconBlock.java @@ -30,6 +30,7 @@ import tech.pegasys.teku.api.schema.deneb.SignedBeaconBlockDeneb; import tech.pegasys.teku.api.schema.deneb.SignedBlindedBeaconBlockDeneb; import tech.pegasys.teku.api.schema.eip7732.SignedBeaconBlockEip7732; +import tech.pegasys.teku.api.schema.eip7732.SignedBlindedBeaconBlockEip7732; import tech.pegasys.teku.api.schema.electra.SignedBeaconBlockElectra; import tech.pegasys.teku.api.schema.electra.SignedBlindedBeaconBlockElectra; import tech.pegasys.teku.api.schema.interfaces.SignedBlock; @@ -69,7 +70,7 @@ public static SignedBeaconBlock create( () -> beaconBlock .toBlindedVersionEip7732() - .map(__ -> new SignedBeaconBlockEip7732(internalBlock)), + .map(__ -> new SignedBlindedBeaconBlockEip7732(internalBlock)), () -> beaconBlock .toVersionEip7732() diff --git a/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBeaconBlockBodyEip7732.java b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBeaconBlockBodyEip7732.java new file mode 100644 index 00000000000..dc1933fa44a --- /dev/null +++ b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBeaconBlockBodyEip7732.java @@ -0,0 +1,143 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.api.schema.eip7732; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.api.schema.Attestation; +import tech.pegasys.teku.api.schema.AttesterSlashing; +import tech.pegasys.teku.api.schema.BLSSignature; +import tech.pegasys.teku.api.schema.Deposit; +import tech.pegasys.teku.api.schema.Eth1Data; +import tech.pegasys.teku.api.schema.ProposerSlashing; +import tech.pegasys.teku.api.schema.SignedVoluntaryExit; +import tech.pegasys.teku.api.schema.altair.BeaconBlockBodyAltair; +import tech.pegasys.teku.api.schema.altair.SyncAggregate; +import tech.pegasys.teku.api.schema.capella.SignedBlsToExecutionChange; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.ssz.schema.SszListSchema; +import tech.pegasys.teku.spec.SpecVersion; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodySchemaEip7732; + +public class BlindedBeaconBlockBodyEip7732 extends BeaconBlockBodyAltair { + + @JsonProperty("bls_to_execution_changes") + public final List blsToExecutionChanges; + + @JsonProperty("signed_execution_payload_header") + public final SignedExecutionPayloadHeader signedExecutionPayloadHeader; + + @JsonProperty("payload_attestations") + public final List payloadAttestations; + + @JsonCreator + public BlindedBeaconBlockBodyEip7732( + @JsonProperty("randao_reveal") final BLSSignature randaoReveal, + @JsonProperty("eth1_data") final Eth1Data eth1Data, + @JsonProperty("graffiti") final Bytes32 graffiti, + @JsonProperty("proposer_slashings") final List proposerSlashings, + @JsonProperty("attester_slashings") final List attesterSlashings, + @JsonProperty("attestations") final List attestations, + @JsonProperty("deposits") final List deposits, + @JsonProperty("voluntary_exits") final List voluntaryExits, + @JsonProperty("sync_aggregate") final SyncAggregate syncAggregate, + @JsonProperty("bls_to_execution_changes") + final List blsToExecutionChanges, + @JsonProperty("signed_execution_payload_header") + final SignedExecutionPayloadHeader signedExecutionPayloadHeader, + @JsonProperty("payload_attestations") final List payloadAttestations) { + super( + randaoReveal, + eth1Data, + graffiti, + proposerSlashings, + attesterSlashings, + attestations, + deposits, + voluntaryExits, + syncAggregate); + checkNotNull(blsToExecutionChanges, "BlsToExecutionChanges is required for Eip7732 blocks"); + this.blsToExecutionChanges = blsToExecutionChanges; + checkNotNull( + signedExecutionPayloadHeader, + "SignedExecutionPayloadHeader is required for Eip7732 blocks"); + this.signedExecutionPayloadHeader = signedExecutionPayloadHeader; + checkNotNull(payloadAttestations, "PayloadAttestations is required for Eip7732 blocks"); + this.payloadAttestations = payloadAttestations; + } + + public BlindedBeaconBlockBodyEip7732( + final tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732 + .BlindedBeaconBlockBodyEip7732 + message) { + super(message); + checkNotNull( + message.getBlsToExecutionChanges(), + "BlsToExecutionChanges are required for Eip7732 blocks"); + this.blsToExecutionChanges = + message.getBlsToExecutionChanges().stream().map(SignedBlsToExecutionChange::new).toList(); + checkNotNull( + message.getSignedExecutionPayloadHeader(), + "SignedExecutionPayloadHeader are required for Eip7732 blocks"); + this.signedExecutionPayloadHeader = + new SignedExecutionPayloadHeader(message.getSignedExecutionPayloadHeader()); + checkNotNull( + message.getPayloadAttestations(), "PayloadAttestations are required for Eip7732 blocks"); + this.payloadAttestations = + message.getPayloadAttestations().stream().map(PayloadAttestation::new).toList(); + } + + @Override + public BeaconBlockBodySchemaEip7732 getBeaconBlockBodySchema(final SpecVersion spec) { + return (BeaconBlockBodySchemaEip7732) + spec.getSchemaDefinitions().getBlindedBeaconBlockBodySchema(); + } + + @Override + public boolean isBlinded() { + return true; + } + + @Override + public BeaconBlockBody asInternalBeaconBlockBody(final SpecVersion spec) { + final SszListSchema< + tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange, ?> + blsToExecutionChangesSchema = + getBeaconBlockBodySchema(spec).getBlsToExecutionChangesSchema(); + return super.asInternalBeaconBlockBody( + spec, + builder -> { + builder.blsToExecutionChanges( + this.blsToExecutionChanges.stream() + .map(b -> b.asInternalSignedBlsToExecutionChange(spec)) + .collect(blsToExecutionChangesSchema.collector())); + builder.signedExecutionPayloadHeader( + signedExecutionPayloadHeader.asInternalSignedExecutionPayloadHeader(spec)); + final SszListSchema< + tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation, ?> + payloadAttestationsSchema = + getBeaconBlockBodySchema(spec).getPayloadAttestationsSchema(); + builder.payloadAttestations( + this.payloadAttestations.stream() + .map(pa -> pa.asInternalPayloadAttestation(spec)) + .collect(payloadAttestationsSchema.collector())); + return SafeFuture.COMPLETE; + }); + } +} diff --git a/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBlockEip7732.java b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBlockEip7732.java new file mode 100644 index 00000000000..19592ce245e --- /dev/null +++ b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/BlindedBlockEip7732.java @@ -0,0 +1,70 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.api.schema.eip7732; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.api.schema.altair.BeaconBlockAltair; +import tech.pegasys.teku.infrastructure.unsigned.UInt64; +import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.SpecVersion; +import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock; +import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockSchema; + +public class BlindedBlockEip7732 extends BeaconBlockAltair { + + public BlindedBlockEip7732(final BeaconBlock message) { + super( + message.getSlot(), + message.getProposerIndex(), + message.getParentRoot(), + message.getStateRoot(), + new BlindedBeaconBlockBodyEip7732( + message.getBody().toBlindedVersionEip7732().orElseThrow())); + } + + @Override + public BeaconBlockSchema getBeaconBlockSchema(final SpecVersion spec) { + return spec.getSchemaDefinitions().getBlindedBeaconBlockSchema(); + } + + @Override + public BeaconBlock asInternalBeaconBlock(final Spec spec) { + final SpecVersion specVersion = spec.atSlot(slot); + return getBeaconBlockSchema(specVersion) + .create( + slot, + proposer_index, + parent_root, + state_root, + body.asInternalBeaconBlockBody(specVersion)); + } + + @JsonProperty("body") + @Override + public BlindedBeaconBlockBodyEip7732 getBody() { + return (BlindedBeaconBlockBodyEip7732) body; + } + + @JsonCreator + public BlindedBlockEip7732( + @JsonProperty("slot") final UInt64 slot, + @JsonProperty("proposer_index") final UInt64 proposerIndex, + @JsonProperty("parent_root") final Bytes32 parentRoot, + @JsonProperty("state_root") final Bytes32 stateRoot, + @JsonProperty("body") final BlindedBeaconBlockBodyEip7732 body) { + super(slot, proposerIndex, parentRoot, stateRoot, body); + } +} diff --git a/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/SignedBlindedBeaconBlockEip7732.java b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/SignedBlindedBeaconBlockEip7732.java new file mode 100644 index 00000000000..436d0ba34b6 --- /dev/null +++ b/data/serializer/src/main/java/tech/pegasys/teku/api/schema/eip7732/SignedBlindedBeaconBlockEip7732.java @@ -0,0 +1,47 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.api.schema.eip7732; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import tech.pegasys.teku.api.schema.BLSSignature; +import tech.pegasys.teku.api.schema.SignedBeaconBlock; +import tech.pegasys.teku.api.schema.interfaces.SignedBlock; + +public class SignedBlindedBeaconBlockEip7732 extends SignedBeaconBlock implements SignedBlock { + private final BlindedBlockEip7732 message; + + public SignedBlindedBeaconBlockEip7732( + final tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock internalBlock) { + super(internalBlock); + checkArgument( + internalBlock.getMessage().getBody().isBlinded(), "requires a signed blinded beacon block"); + this.message = new BlindedBlockEip7732(internalBlock.getMessage()); + } + + @Override + public BlindedBlockEip7732 getMessage() { + return message; + } + + @JsonCreator + public SignedBlindedBeaconBlockEip7732( + @JsonProperty("message") final BlindedBlockEip7732 message, + @JsonProperty("signature") final BLSSignature signature) { + super(message, signature); + this.message = message; + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlock.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlock.java index 7c814014906..9799bf738f8 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlock.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlock.java @@ -87,12 +87,14 @@ private TreeNode getBlindedTree() { } public SignedBeaconBlock unblind( - final SchemaDefinitions schemaDefinitions, final ExecutionPayload payload) { + final SchemaDefinitions schemaDefinitions, final Optional payload) { if (!isBlinded()) { return this; } - - final TreeNode unblindedTree = getUnblindedTree(payload); + if (payload.isEmpty()) { + return this; + } + final TreeNode unblindedTree = getUnblindedTree(payload.get()); return schemaDefinitions.getSignedBeaconBlockSchema().createFromBackingNode(unblindedTree); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBody.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBody.java index a0d9cc171dc..b03b382c527 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBody.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBody.java @@ -29,6 +29,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.deneb.BeaconBlockBodyDeneb; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.deneb.BlindedBeaconBlockBodyDeneb; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodyEip7732; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BlindedBeaconBlockBodyEip7732; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BeaconBlockBodyElectra; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BlindedBeaconBlockBodyElectra; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; @@ -145,7 +146,7 @@ default Optional toBlindedVersionElectra() { return Optional.empty(); } - default Optional toBlindedVersionEip7732() { + default Optional toBlindedVersionEip7732() { return Optional.empty(); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBodySchema.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBodySchema.java index cfd8f1f6773..a955d087269 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBodySchema.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/BeaconBlockBodySchema.java @@ -29,6 +29,7 @@ import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.Deposit; +import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation; import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit; @@ -51,6 +52,10 @@ SafeFuture createBlockBody( SszListSchema getVoluntaryExitsSchema(); + default SszListSchema getPayloadAttestationsSchema() { + throw new UnsupportedOperationException("PayloadAttestations not supported until EIP-7732"); + } + default Optional> toVersionAltair() { return Optional.empty(); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/bellatrix/SignedBeaconBlockUnblinderBellatrix.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/bellatrix/SignedBeaconBlockUnblinderBellatrix.java index 41dfb389e80..969f0070745 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/bellatrix/SignedBeaconBlockUnblinderBellatrix.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/bellatrix/SignedBeaconBlockUnblinderBellatrix.java @@ -16,6 +16,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import java.util.Optional; import java.util.function.Supplier; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; @@ -57,7 +58,7 @@ public SafeFuture unblind() { .hashTreeRoot() .equals(blindedBody.getExecutionPayloadHeader().hashTreeRoot()), "executionPayloadHeader root in blinded block do not match provided executionPayload root"); - return signedBlindedBeaconBlock.unblind(schemaDefinitions, executionPayload); + return signedBlindedBeaconBlock.unblind(schemaDefinitions, Optional.of(executionPayload)); }); } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyBuilderEip7732.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyBuilderEip7732.java index 5b3b4a41064..2e7909b78e4 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyBuilderEip7732.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyBuilderEip7732.java @@ -31,8 +31,9 @@ public class BeaconBlockBodyBuilderEip7732 extends BeaconBlockBodyBuilderElectra private SszList payloadAttestations; public BeaconBlockBodyBuilderEip7732( - final BeaconBlockBodySchema schema) { - super(schema, null); + final BeaconBlockBodySchema schema, + final BeaconBlockBodySchema blindedSchema) { + super(schema, blindedSchema); } @Override @@ -78,9 +79,32 @@ protected void validate() { checkNotNull(payloadAttestations, "payloadAttestations must be specified"); } + @Override + protected Boolean isBlinded() { + return super.isBlinded() || blindedSchema != null; + } + @Override public BeaconBlockBody build() { validate(); + if (isBlinded()) { + final BlindedBeaconBlockBodySchemaEip7732Impl schema = + getAndValidateSchema(true, BlindedBeaconBlockBodySchemaEip7732Impl.class); + return new BlindedBeaconBlockBodyEip7732Impl( + schema, + new SszSignature(randaoReveal), + eth1Data, + SszBytes32.of(graffiti), + proposerSlashings, + attesterSlashings, + attestations, + deposits, + voluntaryExits, + syncAggregate, + getBlsToExecutionChanges(), + signedExecutionPayloadHeader, + payloadAttestations); + } final BeaconBlockBodySchemaEip7732Impl schema = getAndValidateSchema(false, BeaconBlockBodySchemaEip7732Impl.class); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyEip7732.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyEip7732.java index 5a0c9477bb5..1c9d7edc31a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyEip7732.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodyEip7732.java @@ -73,9 +73,4 @@ default SszList getBlobKzgCommitments() { default Optional toVersionEip7732() { return Optional.of(this); } - - @Override - default Optional toBlindedVersionEip7732() { - return Optional.of(this); - } } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732.java index ad140eabd00..6f45f101187 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732.java @@ -16,11 +16,9 @@ import static com.google.common.base.Preconditions.checkArgument; import java.util.Optional; -import tech.pegasys.teku.infrastructure.ssz.schema.SszListSchema; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBodySchema; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BeaconBlockBodySchemaElectra; import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadHeaderSchema; -import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation; public interface BeaconBlockBodySchemaEip7732 extends BeaconBlockBodySchemaElectra { @@ -35,8 +33,6 @@ static BeaconBlockBodySchemaEip7732 required(final BeaconBlockBodySchema s SignedExecutionPayloadHeaderSchema getSignedExecutionPayloadHeaderSchema(); - SszListSchema getPayloadAttestationsSchema(); - long getBlobKzgCommitmentsRootGeneralizedIndex(); @Override diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732Impl.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732Impl.java index f78b3b25b81..929e9b3e985 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732Impl.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BeaconBlockBodySchemaEip7732Impl.java @@ -150,7 +150,7 @@ public static BeaconBlockBodySchemaEip7732Impl create( @Override public SafeFuture createBlockBody( final Function> bodyBuilder) { - final BeaconBlockBodyBuilderEip7732 builder = new BeaconBlockBodyBuilderEip7732(this); + final BeaconBlockBodyBuilderEip7732 builder = new BeaconBlockBodyBuilderEip7732(this, null); return bodyBuilder.apply(builder).thenApply(__ -> builder.build()); } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732.java new file mode 100644 index 00000000000..3b7bf985d4e --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732.java @@ -0,0 +1,65 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732; + +import java.util.Optional; +import tech.pegasys.teku.infrastructure.ssz.SszList; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BlindedBeaconBlockBodyElectra; +import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; + +public interface BlindedBeaconBlockBodyEip7732 extends BlindedBeaconBlockBodyElectra { + static BlindedBeaconBlockBodyEip7732 required(final BeaconBlockBody body) { + return body.toBlindedVersionEip7732() + .orElseThrow( + () -> + new IllegalArgumentException( + "Expected an Eip7732 blinded block body but got " + + body.getClass().getSimpleName())); + } + + @Override + BlindedBeaconBlockBodySchemaEip7732 getSchema(); + + SignedExecutionPayloadHeader getSignedExecutionPayloadHeader(); + + SszList getPayloadAttestations(); + + @Override + default Optional> getOptionalBlobKzgCommitments() { + return Optional.empty(); + } + + @Override + default Optional getOptionalSignedExecutionPayloadHeader() { + return Optional.of(getSignedExecutionPayloadHeader()); + } + + @Override + default Optional> getOptionalPayloadAttestations() { + return Optional.of(getPayloadAttestations()); + } + + @Override + default SszList getBlobKzgCommitments() { + throw new UnsupportedOperationException("BlobKzgCommitments removed in Eip7732"); + } + + @Override + default Optional toBlindedVersionEip7732() { + return Optional.of(this); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732Impl.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732Impl.java new file mode 100644 index 00000000000..fa63063a651 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodyEip7732Impl.java @@ -0,0 +1,181 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732; + +import static com.google.common.base.Preconditions.checkArgument; + +import org.apache.tuweni.bytes.Bytes32; +import tech.pegasys.teku.bls.BLSSignature; +import tech.pegasys.teku.infrastructure.ssz.SszList; +import tech.pegasys.teku.infrastructure.ssz.containers.Container12; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; +import tech.pegasys.teku.spec.datastructures.blocks.Eth1Data; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.SyncAggregate; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.operations.Attestation; +import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; +import tech.pegasys.teku.spec.datastructures.operations.Deposit; +import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation; +import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; +import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; +import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit; +import tech.pegasys.teku.spec.datastructures.type.SszSignature; + +public class BlindedBeaconBlockBodyEip7732Impl + extends Container12< + BlindedBeaconBlockBodyEip7732Impl, + SszSignature, + Eth1Data, + SszBytes32, + SszList, + SszList, + SszList, + SszList, + SszList, + SyncAggregate, + SszList, + SignedExecutionPayloadHeader, + SszList> + implements BlindedBeaconBlockBodyEip7732 { + + BlindedBeaconBlockBodyEip7732Impl( + final BlindedBeaconBlockBodySchemaEip7732Impl type, + final SszSignature randaoReveal, + final Eth1Data eth1Data, + final SszBytes32 graffiti, + final SszList proposerSlashings, + final SszList attesterSlashings, + final SszList attestations, + final SszList deposits, + final SszList voluntaryExits, + final SyncAggregate syncAggregate, + final SszList blsToExecutionChanges, + final SignedExecutionPayloadHeader signedExecutionPayloadHeader, + final SszList payloadAttestations) { + super( + type, + randaoReveal, + eth1Data, + graffiti, + proposerSlashings, + attesterSlashings, + attestations, + deposits, + voluntaryExits, + syncAggregate, + blsToExecutionChanges, + signedExecutionPayloadHeader, + payloadAttestations); + } + + BlindedBeaconBlockBodyEip7732Impl(final BlindedBeaconBlockBodySchemaEip7732Impl type) { + super(type); + } + + BlindedBeaconBlockBodyEip7732Impl( + final BlindedBeaconBlockBodySchemaEip7732Impl type, final TreeNode backingNode) { + super(type, backingNode); + } + + public static BlindedBeaconBlockBodyEip7732Impl required(final BeaconBlockBody body) { + checkArgument( + body instanceof BlindedBeaconBlockBodyEip7732Impl, + "Expected Eip7732 blinded block body but got %s", + body.getClass()); + return (BlindedBeaconBlockBodyEip7732Impl) body; + } + + @Override + public ExecutionPayloadHeader getExecutionPayloadHeader() { + return getSignedExecutionPayloadHeader().getMessage(); + } + + @Override + public BLSSignature getRandaoReveal() { + return getField0().getSignature(); + } + + @Override + public SszSignature getRandaoRevealSsz() { + return getField0(); + } + + @Override + public Eth1Data getEth1Data() { + return getField1(); + } + + @Override + public Bytes32 getGraffiti() { + return getField2().get(); + } + + @Override + public SszBytes32 getGraffitiSsz() { + return getField2(); + } + + @Override + public SszList getProposerSlashings() { + return getField3(); + } + + @Override + public SszList getAttesterSlashings() { + return getField4(); + } + + @Override + public SszList getAttestations() { + return getField5(); + } + + @Override + public SszList getDeposits() { + return getField6(); + } + + @Override + public SszList getVoluntaryExits() { + return getField7(); + } + + @Override + public SyncAggregate getSyncAggregate() { + return getField8(); + } + + @Override + public SszList getBlsToExecutionChanges() { + return getField9(); + } + + @Override + public SignedExecutionPayloadHeader getSignedExecutionPayloadHeader() { + return getField10(); + } + + @Override + public SszList getPayloadAttestations() { + return getField11(); + } + + @Override + public BlindedBeaconBlockBodySchemaEip7732Impl getSchema() { + return (BlindedBeaconBlockBodySchemaEip7732Impl) super.getSchema(); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732.java new file mode 100644 index 00000000000..a5ee9df4421 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732.java @@ -0,0 +1,31 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732; + +import static com.google.common.base.Preconditions.checkArgument; + +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBodySchema; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BlindedBeaconBlockBodySchemaElectra; + +public interface BlindedBeaconBlockBodySchemaEip7732 + extends BlindedBeaconBlockBodySchemaElectra { + + static BlindedBeaconBlockBodySchemaEip7732 required(final BeaconBlockBodySchema schema) { + checkArgument( + schema instanceof BlindedBeaconBlockBodySchemaEip7732, + "Expected a BlindedBeaconBlockBodySchemaEip7732 but was %s", + schema.getClass()); + return (BlindedBeaconBlockBodySchemaEip7732) schema; + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732Impl.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732Impl.java new file mode 100644 index 00000000000..3255968de98 --- /dev/null +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/blocks/blockbody/versions/eip7732/BlindedBeaconBlockBodySchemaEip7732Impl.java @@ -0,0 +1,232 @@ +/* + * Copyright Consensys Software Inc., 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732; + +import it.unimi.dsi.fastutil.longs.LongList; +import java.util.function.Function; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.ssz.SszList; +import tech.pegasys.teku.infrastructure.ssz.containers.ContainerSchema12; +import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32; +import tech.pegasys.teku.infrastructure.ssz.schema.SszListSchema; +import tech.pegasys.teku.infrastructure.ssz.schema.SszPrimitiveSchemas; +import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode; +import tech.pegasys.teku.spec.config.SpecConfigEip7732; +import tech.pegasys.teku.spec.datastructures.blocks.Eth1Data; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBodyBuilder; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.common.BlockBodyFields; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.SyncAggregate; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.SyncAggregateSchema; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadHeaderSchema; +import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadHeader; +import tech.pegasys.teku.spec.datastructures.execution.SignedExecutionPayloadHeaderSchema; +import tech.pegasys.teku.spec.datastructures.operations.Attestation; +import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; +import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing.AttesterSlashingSchema; +import tech.pegasys.teku.spec.datastructures.operations.Deposit; +import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation; +import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestationSchema; +import tech.pegasys.teku.spec.datastructures.operations.ProposerSlashing; +import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; +import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChangeSchema; +import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit; +import tech.pegasys.teku.spec.datastructures.operations.versions.electra.AttestationElectraSchema; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; +import tech.pegasys.teku.spec.datastructures.type.SszSignature; +import tech.pegasys.teku.spec.datastructures.type.SszSignatureSchema; + +public class BlindedBeaconBlockBodySchemaEip7732Impl + extends ContainerSchema12< + BlindedBeaconBlockBodyEip7732Impl, + SszSignature, + Eth1Data, + SszBytes32, + SszList, + SszList, + SszList, + SszList, + SszList, + SyncAggregate, + SszList, + SignedExecutionPayloadHeader, + SszList> + implements BlindedBeaconBlockBodySchemaEip7732 { + + protected BlindedBeaconBlockBodySchemaEip7732Impl( + final String containerName, + final NamedSchema randaoRevealSchema, + final NamedSchema eth1DataSchema, + final NamedSchema graffitiSchema, + final NamedSchema> proposerSlashingsSchema, + final NamedSchema> attesterSlashingsSchema, + final NamedSchema> attestationsSchema, + final NamedSchema> depositsSchema, + final NamedSchema> voluntaryExitsSchema, + final NamedSchema syncAggregateSchema, + final NamedSchema> blsToExecutionChange, + final NamedSchema signedExecutionPayloadHeader, + final NamedSchema> payloadAttestations) { + super( + containerName, + randaoRevealSchema, + eth1DataSchema, + graffitiSchema, + proposerSlashingsSchema, + attesterSlashingsSchema, + attestationsSchema, + depositsSchema, + voluntaryExitsSchema, + syncAggregateSchema, + blsToExecutionChange, + signedExecutionPayloadHeader, + payloadAttestations); + } + + public static BlindedBeaconBlockBodySchemaEip7732Impl create( + final SpecConfigEip7732 specConfig, + final AttesterSlashingSchema attesterSlashingSchema, + final SignedBlsToExecutionChangeSchema blsToExecutionChangeSchema, + final long maxValidatorsPerAttestation, + final ExecutionPayloadHeaderSchema executionPayloadHeaderSchema, + final PayloadAttestationSchema payloadAttestationSchema, + final String containerName) { + return new BlindedBeaconBlockBodySchemaEip7732Impl( + containerName, + namedSchema(BlockBodyFields.RANDAO_REVEAL, SszSignatureSchema.INSTANCE), + namedSchema(BlockBodyFields.ETH1_DATA, Eth1Data.SSZ_SCHEMA), + namedSchema(BlockBodyFields.GRAFFITI, SszPrimitiveSchemas.BYTES32_SCHEMA), + namedSchema( + BlockBodyFields.PROPOSER_SLASHINGS, + SszListSchema.create( + ProposerSlashing.SSZ_SCHEMA, specConfig.getMaxProposerSlashings())), + namedSchema( + BlockBodyFields.ATTESTER_SLASHINGS, + SszListSchema.create( + attesterSlashingSchema, specConfig.getMaxAttesterSlashingsElectra())), + namedSchema( + BlockBodyFields.ATTESTATIONS, + SszListSchema.create( + new AttestationElectraSchema( + maxValidatorsPerAttestation, specConfig.getMaxCommitteesPerSlot()) + .castTypeToAttestationSchema(), + specConfig.getMaxAttestationsElectra())), + namedSchema( + BlockBodyFields.DEPOSITS, + SszListSchema.create(Deposit.SSZ_SCHEMA, specConfig.getMaxDeposits())), + namedSchema( + BlockBodyFields.VOLUNTARY_EXITS, + SszListSchema.create( + SignedVoluntaryExit.SSZ_SCHEMA, specConfig.getMaxVoluntaryExits())), + namedSchema( + BlockBodyFields.SYNC_AGGREGATE, + SyncAggregateSchema.create(specConfig.getSyncCommitteeSize())), + namedSchema( + BlockBodyFields.BLS_TO_EXECUTION_CHANGES, + SszListSchema.create( + blsToExecutionChangeSchema, specConfig.getMaxBlsToExecutionChanges())), + namedSchema( + BlockBodyFields.SIGNED_EXECUTION_PAYLOAD_HEADER, + new SignedExecutionPayloadHeaderSchema(executionPayloadHeaderSchema)), + namedSchema( + BlockBodyFields.PAYLOAD_ATTESTATIONS, + SszListSchema.create( + payloadAttestationSchema, specConfig.getMaxPayloadAttestations()))); + } + + @Override + public SafeFuture createBlockBody( + final Function> bodyBuilder) { + final BeaconBlockBodyBuilderEip7732 builder = new BeaconBlockBodyBuilderEip7732(null, this); + return bodyBuilder.apply(builder).thenApply(__ -> builder.build()); + } + + @Override + public BlindedBeaconBlockBodyEip7732Impl createEmpty() { + return new BlindedBeaconBlockBodyEip7732Impl(this); + } + + @SuppressWarnings("unchecked") + @Override + public SszListSchema getProposerSlashingsSchema() { + return (SszListSchema) + getChildSchema(getFieldIndex(BlockBodyFields.PROPOSER_SLASHINGS)); + } + + @SuppressWarnings("unchecked") + @Override + public SszListSchema getAttesterSlashingsSchema() { + return (SszListSchema) + getChildSchema(getFieldIndex(BlockBodyFields.ATTESTER_SLASHINGS)); + } + + @SuppressWarnings("unchecked") + @Override + public SszListSchema getAttestationsSchema() { + return (SszListSchema) + getChildSchema(getFieldIndex(BlockBodyFields.ATTESTATIONS)); + } + + @SuppressWarnings("unchecked") + @Override + public SszListSchema getDepositsSchema() { + return (SszListSchema) getChildSchema(getFieldIndex(BlockBodyFields.DEPOSITS)); + } + + @SuppressWarnings("unchecked") + @Override + public SszListSchema getVoluntaryExitsSchema() { + return (SszListSchema) + getChildSchema(getFieldIndex(BlockBodyFields.VOLUNTARY_EXITS)); + } + + @SuppressWarnings("unchecked") + @Override + public SszListSchema getPayloadAttestationsSchema() { + return (SszListSchema) + getChildSchema(getFieldIndex(BlockBodyFields.PAYLOAD_ATTESTATIONS)); + } + + @Override + public SyncAggregateSchema getSyncAggregateSchema() { + return (SyncAggregateSchema) getChildSchema(getFieldIndex(BlockBodyFields.SYNC_AGGREGATE)); + } + + @Override + public BlindedBeaconBlockBodyEip7732Impl createFromBackingNode(final TreeNode node) { + return new BlindedBeaconBlockBodyEip7732Impl(this, node); + } + + @Override + public SszListSchema getBlobKzgCommitmentsSchema() { + throw new UnsupportedOperationException("BlobKzgCommitments removed in Eip7732"); + } + + @Override + public LongList getBlindedNodeGeneralizedIndices() { + return LongList.of(); + } + + @Override + public SszListSchema getBlsToExecutionChanges() { + return null; + } + + @Override + public ExecutionPayloadHeaderSchema getExecutionPayloadHeaderSchema() { + return ((SignedExecutionPayloadHeaderSchema) + getChildSchema(getFieldIndex(BlockBodyFields.SIGNED_EXECUTION_PAYLOAD_HEADER))) + .getMessageSchema(); + } +} diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7732.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7732.java index 372e02d3d52..9781f0f8413 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7732.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaDefinitionsEip7732.java @@ -30,6 +30,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBodySchema; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodyBuilderEip7732; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodySchemaEip7732Impl; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BlindedBeaconBlockBodySchemaEip7732Impl; import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.BlockContentsSchema; import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.SignedBlockContentsSchema; import tech.pegasys.teku.spec.datastructures.builder.BlobsBundleSchema; @@ -70,9 +71,12 @@ public class SchemaDefinitionsEip7732 extends SchemaDefinitionsElectra { private final ExecutionPayloadHeaderSchemaEip7732 executionPayloadHeaderSchemaEip7732; private final BeaconBlockBodySchemaEip7732Impl beaconBlockBodySchema; + private final BlindedBeaconBlockBodySchemaEip7732Impl blindedBeaconBlockBodySchema; private final BeaconBlockSchema beaconBlockSchema; + private final BeaconBlockSchema blindedBeaconBlockSchema; private final SignedBeaconBlockSchema signedBeaconBlockSchema; + private final SignedBeaconBlockSchema signedBlindedBeaconBlockSchema; private final BuilderBidSchema builderBidSchemaElectra; private final SignedBuilderBidSchema signedBuilderBidSchemaElectra; @@ -119,9 +123,22 @@ public SchemaDefinitionsEip7732(final SpecConfigEip7732 specConfig) { executionPayloadHeaderSchemaEip7732, payloadAttestationSchema, "BeaconBlockBodyEip7732"); + this.blindedBeaconBlockBodySchema = + BlindedBeaconBlockBodySchemaEip7732Impl.create( + specConfig, + getAttesterSlashingSchema(), + getSignedBlsToExecutionChangeSchema(), + maxValidatorsPerAttestation, + executionPayloadHeaderSchemaEip7732, + payloadAttestationSchema, + "BlindedBlockBodyEip7732"); this.beaconBlockSchema = new BeaconBlockSchema(beaconBlockBodySchema, "BeaconBlockEip7732"); + this.blindedBeaconBlockSchema = + new BeaconBlockSchema(blindedBeaconBlockBodySchema, "BlindedBlockEip7732"); this.signedBeaconBlockSchema = new SignedBeaconBlockSchema(beaconBlockSchema, "SignedBeaconBlockEip7732"); + this.signedBlindedBeaconBlockSchema = + new SignedBeaconBlockSchema(blindedBeaconBlockSchema, "SignedBlindedBlockEip7732"); this.builderBidSchemaElectra = new BuilderBidSchemaDeneb( "BuilderBidEip7732", @@ -202,7 +219,7 @@ public BeaconBlockBodySchema getBeaconBlockBodySchema() { @Override public BeaconBlockBodySchema getBlindedBeaconBlockBodySchema() { - return beaconBlockBodySchema; + return blindedBeaconBlockBodySchema; } @Override @@ -212,7 +229,7 @@ public BeaconBlockSchema getBeaconBlockSchema() { @Override public BeaconBlockSchema getBlindedBeaconBlockSchema() { - return beaconBlockSchema; + return blindedBeaconBlockSchema; } @Override @@ -222,7 +239,7 @@ public SignedBeaconBlockSchema getSignedBeaconBlockSchema() { @Override public SignedBeaconBlockSchema getSignedBlindedBeaconBlockSchema() { - return signedBeaconBlockSchema; + return signedBlindedBeaconBlockSchema; } @Override @@ -272,7 +289,7 @@ public BuilderPayloadSchema getBuilderPayloadSchema() { @Override public BeaconBlockBodyBuilder createBeaconBlockBodyBuilder() { - return new BeaconBlockBodyBuilderEip7732(beaconBlockBodySchema); + return new BeaconBlockBodyBuilderEip7732(beaconBlockBodySchema, blindedBeaconBlockBodySchema); } @Override diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlockTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlockTest.java index 5565055efc4..c8afc74b8b6 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlockTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/datastructures/blocks/SignedBeaconBlockTest.java @@ -24,7 +24,6 @@ import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecContext; import tech.pegasys.teku.spec.TestSpecInvocationContextProvider.SpecContext; -import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; import tech.pegasys.teku.spec.schemas.SchemaDefinitions; import tech.pegasys.teku.spec.util.DataStructureUtil; @@ -59,8 +58,7 @@ void shouldBlindAndUnblind() { final SignedBeaconBlock blinded = original.blind(spec.getGenesisSchemaDefinitions()); assertThat(blinded.hashTreeRoot()).isEqualTo(original.hashTreeRoot()); - if (!blinded.getMessage().getBody().isBlinded() - && !milestone.isGreaterThanOrEqualTo(SpecMilestone.EIP7732)) { + if (!blinded.getMessage().getBody().isBlinded()) { // Didn't blind the block so we must have a spec prior to bellatrix that doesn't have payloads assertThat(milestone.isGreaterThanOrEqualTo(SpecMilestone.BELLATRIX)).isFalse(); } else { @@ -74,14 +72,10 @@ void shouldBlindAndUnblind() { spec.getGenesisSchemaDefinitions() .getSignedBlindedBeaconBlockSchema() .getJsonTypeDefinition())); - - // Otherwise, we should be able to unblind it again - final ExecutionPayload executionPayload = - milestone.isGreaterThanOrEqualTo(SpecMilestone.EIP7732) - ? null - : original.getMessage().getBody().getOptionalExecutionPayload().orElseThrow(); final SignedBeaconBlock unblinded = - blinded.unblind(spec.getGenesisSchemaDefinitions(), executionPayload); + blinded.unblind( + spec.getGenesisSchemaDefinitions(), + original.getMessage().getBody().getOptionalExecutionPayload()); assertThat(unblinded.hashTreeRoot()).isEqualTo(original.hashTreeRoot()); assertThat(unblinded.sszSerialize()).isEqualTo(original.sszSerialize()); assertThatNoException() diff --git a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java index 13403772aec..6895d6a4c70 100644 --- a/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java +++ b/ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java @@ -109,7 +109,6 @@ import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.capella.BeaconBlockBodySchemaCapella; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.deneb.BeaconBlockBodyDeneb; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.deneb.BeaconBlockBodySchemaDeneb; -import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodySchemaEip7732; import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.BlockContents; import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.SignedBlockContents; import tech.pegasys.teku.spec.datastructures.builder.BlobsBundleSchema; @@ -1351,10 +1350,7 @@ public BeaconBlockBody randomBlindedBeaconBlockBody( if (builder.supportsPayloadAttestations()) { builder.payloadAttestations( randomSszList( - BeaconBlockBodySchemaEip7732.required(schema) - .getPayloadAttestationsSchema(), - this::randomPayloadAttestation, - 3)); + schema.getPayloadAttestationsSchema(), this::randomPayloadAttestation, 3)); } builderModifier.accept(builder); return SafeFuture.COMPLETE; @@ -1464,10 +1460,7 @@ public BeaconBlockBody randomBeaconBlockBody( if (builder.supportsPayloadAttestations()) { builder.payloadAttestations( randomSszList( - BeaconBlockBodySchemaEip7732.required(schema) - .getPayloadAttestationsSchema(), - this::randomPayloadAttestation, - 3)); + schema.getPayloadAttestationsSchema(), this::randomPayloadAttestation, 3)); } builderModifier.accept(builder); return SafeFuture.COMPLETE; @@ -1529,9 +1522,7 @@ public BeaconBlockBody randomFullBeaconBlockBody( if (builder.supportsPayloadAttestations()) { builder.payloadAttestations( randomFullSszList( - BeaconBlockBodySchemaEip7732.required(schema) - .getPayloadAttestationsSchema(), - this::randomPayloadAttestation)); + schema.getPayloadAttestationsSchema(), this::randomPayloadAttestation)); } builderModifier.accept(builder); return SafeFuture.COMPLETE; diff --git a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/attestation/PayloadAttestationPool.java b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/attestation/PayloadAttestationPool.java index 440fcde4ca4..7059eb700b7 100644 --- a/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/attestation/PayloadAttestationPool.java +++ b/ethereum/statetransition/src/main/java/tech/pegasys/teku/statetransition/attestation/PayloadAttestationPool.java @@ -21,7 +21,6 @@ import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.infrastructure.ssz.schema.SszListSchema; import tech.pegasys.teku.spec.Spec; -import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip7732.BeaconBlockBodySchemaEip7732; import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestation; import tech.pegasys.teku.spec.datastructures.operations.PayloadAttestationMessage; import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState; @@ -64,8 +63,7 @@ public synchronized SszList getPayloadAttestationsForBlock( spec.atSlot(stateAtBlockSlot.getSlot()).getSchemaDefinitions(); final SszListSchema attestationsSchema = - BeaconBlockBodySchemaEip7732.required(schemaDefinitions.getBeaconBlockBodySchema()) - .getPayloadAttestationsSchema(); + schemaDefinitions.getBeaconBlockBodySchema().getPayloadAttestationsSchema(); return attestationsSchema.createFromElements(List.of()); }