From 0067d57e97dbe143c6e23a9b8d3925591e19dcf5 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Thu, 10 Oct 2024 14:16:46 +1300 Subject: [PATCH] Add executionRequestHash to NewPayloadRequest as part of block validation flow (#8700) --- .../electra/block/BlockProcessorElectra.java | 30 +++++++++++ .../block/BlockProcessorElectraTest.java | 51 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java index 83ce065d599..ed5a8a7b684 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java @@ -30,6 +30,7 @@ import tech.pegasys.teku.bls.BLSSignature; import tech.pegasys.teku.ethereum.execution.types.Eth1Address; import tech.pegasys.teku.infrastructure.bytes.Bytes20; +import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.infrastructure.ssz.SszMutableList; import tech.pegasys.teku.infrastructure.ssz.collections.SszBitlist; import tech.pegasys.teku.infrastructure.ssz.primitive.SszByte; @@ -41,11 +42,14 @@ import tech.pegasys.teku.spec.config.SpecConfigElectra; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BeaconBlockBodyElectra; +import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; import tech.pegasys.teku.spec.datastructures.execution.ExpectedWithdrawals; +import tech.pegasys.teku.spec.datastructures.execution.NewPayloadRequest; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ConsolidationRequest; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequest; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequests; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsDataCodec; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.WithdrawalRequest; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.Deposit; @@ -56,6 +60,7 @@ import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.MutableBeaconStateElectra; import tech.pegasys.teku.spec.datastructures.state.versions.electra.PendingConsolidation; import tech.pegasys.teku.spec.datastructures.state.versions.electra.PendingDeposit; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; import tech.pegasys.teku.spec.datastructures.type.SszPublicKey; import tech.pegasys.teku.spec.datastructures.type.SszSignature; import tech.pegasys.teku.spec.logic.common.helpers.BeaconStateMutators.ValidatorExitContext; @@ -70,6 +75,7 @@ import tech.pegasys.teku.spec.logic.common.util.SyncCommitteeUtil; import tech.pegasys.teku.spec.logic.common.util.ValidatorsUtil; import tech.pegasys.teku.spec.logic.versions.deneb.block.BlockProcessorDeneb; +import tech.pegasys.teku.spec.logic.versions.deneb.types.VersionedHash; import tech.pegasys.teku.spec.logic.versions.electra.helpers.BeaconStateAccessorsElectra; import tech.pegasys.teku.spec.logic.versions.electra.helpers.BeaconStateMutatorsElectra; import tech.pegasys.teku.spec.logic.versions.electra.helpers.MiscHelpersElectra; @@ -85,6 +91,7 @@ public class BlockProcessorElectra extends BlockProcessorDeneb { private final BeaconStateMutatorsElectra beaconStateMutatorsElectra; private final BeaconStateAccessorsElectra beaconStateAccessorsElectra; private final SchemaDefinitionsElectra schemaDefinitionsElectra; + private final ExecutionRequestsDataCodec executionRequestsDataCodec; public BlockProcessorElectra( final SpecConfigElectra specConfig, @@ -117,6 +124,29 @@ public BlockProcessorElectra( this.beaconStateMutatorsElectra = beaconStateMutators; this.beaconStateAccessorsElectra = beaconStateAccessors; this.schemaDefinitionsElectra = schemaDefinitions; + this.executionRequestsDataCodec = + new ExecutionRequestsDataCodec(schemaDefinitions.getExecutionRequestsSchema()); + } + + @Override + public NewPayloadRequest computeNewPayloadRequest( + final BeaconState state, final BeaconBlockBody beaconBlockBody) + throws BlockProcessingException { + final ExecutionPayload executionPayload = extractExecutionPayload(beaconBlockBody); + final SszList blobKzgCommitments = extractBlobKzgCommitments(beaconBlockBody); + final List versionedHashes = + blobKzgCommitments.stream() + .map(SszKZGCommitment::getKZGCommitment) + .map(miscHelpers::kzgCommitmentToVersionedHash) + .toList(); + final Bytes32 parentBeaconBlockRoot = state.getLatestBlockHeader().getParentRoot(); + final ExecutionRequests executionRequests = + BeaconBlockBodyElectra.required(beaconBlockBody).getExecutionRequests(); + return new NewPayloadRequest( + executionPayload, + versionedHashes, + parentBeaconBlockRoot, + executionRequestsDataCodec.hash(executionRequests)); } @Override diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java index 9d3dd4b9500..3add055fa7f 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.IntStream; import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; @@ -28,11 +29,16 @@ import tech.pegasys.teku.infrastructure.ssz.primitive.SszUInt64; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.Spec; +import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecFactory; +import tech.pegasys.teku.spec.config.SpecConfigDeneb; import tech.pegasys.teku.spec.config.SpecConfigElectra; 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.electra.BeaconBlockBodyElectra; +import tech.pegasys.teku.spec.datastructures.execution.NewPayloadRequest; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositRequest; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsDataCodec; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.WithdrawalRequest; import tech.pegasys.teku.spec.datastructures.operations.DepositData; import tech.pegasys.teku.spec.datastructures.state.Validator; @@ -40,10 +46,14 @@ import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.BeaconStateElectra; import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.electra.MutableBeaconStateElectra; import tech.pegasys.teku.spec.datastructures.state.versions.electra.PendingPartialWithdrawal; +import tech.pegasys.teku.spec.datastructures.type.SszKZGCommitment; import tech.pegasys.teku.spec.logic.common.helpers.BeaconStateMutators.ValidatorExitContext; +import tech.pegasys.teku.spec.logic.common.helpers.MiscHelpers; import tech.pegasys.teku.spec.logic.common.statetransition.exceptions.BlockProcessingException; import tech.pegasys.teku.spec.logic.versions.deneb.block.BlockProcessorDenebTest; +import tech.pegasys.teku.spec.logic.versions.deneb.types.VersionedHash; import tech.pegasys.teku.spec.logic.versions.electra.util.AttestationUtilElectra; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionsElectra; class BlockProcessorElectraTest extends BlockProcessorDenebTest { @@ -524,6 +534,40 @@ void shouldUseElectraAttestationUtil() { .isInstanceOf(AttestationUtilElectra.class); } + @Test + public void shouldCreateNewPayloadRequestWithExecutionRequestsHash() throws Exception { + final BeaconState preState = createBeaconState(); + final BeaconBlockBodyElectra blockBody = + BeaconBlockBodyElectra.required(dataStructureUtil.randomBeaconBlockBodyWithCommitments(3)); + final MiscHelpers miscHelpers = spec.atSlot(UInt64.ONE).miscHelpers(); + final List expectedVersionedHashes = + blockBody.getOptionalBlobKzgCommitments().orElseThrow().stream() + .map(SszKZGCommitment::getKZGCommitment) + .map(miscHelpers::kzgCommitmentToVersionedHash) + .collect(Collectors.toList()); + final Bytes32 expectedExecutionRequestsHash = + getExecutionRequestsDataCodec().hash(blockBody.getExecutionRequests()); + + final NewPayloadRequest newPayloadRequest = + spec.getBlockProcessor(UInt64.ONE).computeNewPayloadRequest(preState, blockBody); + + assertThat(newPayloadRequest.getExecutionPayload()) + .isEqualTo(blockBody.getOptionalExecutionPayload().orElseThrow()); + assertThat(newPayloadRequest.getVersionedHashes()).isPresent(); + assertThat(newPayloadRequest.getVersionedHashes().get()) + .hasSize(3) + .allSatisfy( + versionedHash -> + assertThat(versionedHash.getVersion()) + .isEqualTo(SpecConfigDeneb.VERSIONED_HASH_VERSION_KZG)) + .hasSameElementsAs(expectedVersionedHashes); + assertThat(newPayloadRequest.getParentBeaconBlockRoot()).isPresent(); + assertThat(newPayloadRequest.getParentBeaconBlockRoot().get()) + .isEqualTo(preState.getLatestBlockHeader().getParentRoot()); + assertThat(newPayloadRequest.getExecutionRequestsHash()) + .hasValue(expectedExecutionRequestsHash); + } + private Supplier validatorExitContextSupplier(final BeaconState state) { return spec.getGenesisSpec().beaconStateMutators().createValidatorExitContextSupplier(state); } @@ -531,4 +575,11 @@ private Supplier validatorExitContextSupplier(final Beacon private BlockProcessorElectra getBlockProcessor(final BeaconState state) { return (BlockProcessorElectra) spec.getBlockProcessor(state.getSlot()); } + + private ExecutionRequestsDataCodec getExecutionRequestsDataCodec() { + return new ExecutionRequestsDataCodec( + SchemaDefinitionsElectra.required( + spec.forMilestone(SpecMilestone.ELECTRA).getSchemaDefinitions()) + .getExecutionRequestsSchema()); + } }