diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v4_validator_blocks_{slot}.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v4_validator_blocks_{slot}.json new file mode 100644 index 00000000000..12b1c631ef7 --- /dev/null +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v4_validator_blocks_{slot}.json @@ -0,0 +1,152 @@ +{ + "get" : { + "tags" : [ "Validator", "Validator Required Api" ], + "operationId" : "produceBlockV4", + "summary" : "Produce a new block, without signature.", + "description" : "Requests a beacon node to produce a valid block for post-Gloas (ePBS), which can then be signed by a validator.\nSupports two operational modes controlled by `include_payload`:\n\n- **Stateless mode** (`include_payload=true`, default): Returns the execution payload envelope and blobs\n inline, suitable for multi-BN operations.\n- **Stateful mode** (`include_payload=false`): The beacon node caches the payload for separate retrieval\n via `/eth/v1/validator/execution_payload_envelope/{slot}/{beacon_block_root}`.\n", + "parameters" : [ { + "name" : "slot", + "required" : true, + "in" : "path", + "schema" : { + "type" : "string", + "description" : "The slot for which the block should be proposed.", + "example" : "1", + "format" : "uint64" + } + }, { + "name" : "randao_reveal", + "required" : true, + "in" : "query", + "schema" : { + "type" : "string", + "description" : "`BLSSignature Hex` BLS12-381 signature for the current epoch.", + "example" : "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "format" : "byte" + } + }, { + "name" : "graffiti", + "in" : "query", + "schema" : { + "type" : "string", + "description" : "`Bytes32 Hex` Graffiti.", + "example" : "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "format" : "byte" + } + }, { + "name" : "builder_boost_factor", + "in" : "query", + "schema" : { + "type" : "string", + "description" : "Percentage multiplier to apply to the builder's payload value when choosing between a\nbuilder payload header and payload from the paired execution node. This parameter is only\nrelevant if the beacon node is connected to a builder, deems it safe to produce a builder\npayload, and receives valid responses from both the builder endpoint _and_ the paired\nexecution node. When these preconditions are met, the server MUST act as follows:\n\n* if `exec_node_payload_value >= builder_boost_factor * (builder_payload_value // 100)`,\n then return a full (unblinded) block containing the execution node payload.\n* otherwise, return a blinded block containing the builder payload header.\n\nServers must support the following values of the boost factor which encode common\npreferences:\n\n* `builder_boost_factor=0`: prefer the execution node payload unless an error makes it\n unviable.\n* `builder_boost_factor=100`: default profit maximization mode; choose whichever\n payload pays more.\n* `builder_boost_factor=2**64 - 1`: prefer the builder payload unless an error or\n beacon node health check makes it unviable.\n\nServers should use saturating arithmetic or another technique to ensure that large values of\nthe `builder_boost_factor` do not trigger overflows or errors. If this parameter is\nprovided and the beacon node is not configured with a builder then the beacon node MUST\nrespond with a full block, which the caller can choose to reject if it wishes. If this\nparameter is **not** provided then it should be treated as having the default value of 100.\nIf the value is provided but out of range for a 64-bit unsigned integer, then an error\nresponse with status code 400 MUST be returned.", + "example" : "1", + "format" : "uint64" + } + }, { + "name" : "include_payload", + "in" : "query", + "schema" : { + "type" : "boolean", + "description" : "If true, returns the execution payload envelope and blobs inline in the response (stateless mode, suitable for multi-BN setups). If false, the beacon node caches the payload for separate retrieval. Default: true." + } + }, { + "name" : "skip_randao_verification", + "allowEmptyValue" : true, + "in" : "query", + "schema" : { + "type" : "string", + "description" : "Skip verification of the `randao_reveal` value. Ignored in the Teku implementation.", + "minLength" : 0, + "maxLength" : 0 + } + } ], + "responses" : { + "200" : { + "description" : "Request successful", + "headers" : { + "Eth-Consensus-Version" : { + "description" : "Required in response so client can deserialize returned json or ssz data more effectively.", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ "phase0", "altair", "bellatrix", "capella", "deneb", "electra", "fulu", "gloas", "heze" ], + "example" : "phase0" + } + }, + "Eth-Execution-Payload-Included" : { + "description" : "Required in response so client can determine whether execution payload is included inline.", + "required" : true, + "schema" : { + "type" : "boolean" + } + }, + "Eth-Consensus-Block-Value" : { + "description" : "Consensus rewards for this block in Wei paid to the proposer. The rewards value is the sum of values of the proposer rewards from attestations, sync committees and slashings included in the proposal. Required in response so client can determine relative value of consensus blocks.", + "required" : true, + "schema" : { + "type" : "string", + "example" : "1" + } + } + }, + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ProduceBlockV4Response" + } + }, + "application/octet-stream" : { + "schema" : { + "type" : "string", + "format" : "binary" + } + } + } + }, + "503" : { + "description" : "Service unavailable", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HttpErrorResponse" + } + } + } + }, + "204" : { + "description" : "Data is unavailable because the chain has not yet reached genesis", + "content" : { } + }, + "501" : { + "description" : "Not implemented", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HttpErrorResponse" + } + } + } + }, + "400" : { + "description" : "The request could not be processed, check the response for more information.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HttpErrorResponse" + } + } + } + }, + "500" : { + "description" : "Internal server error", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/HttpErrorResponse" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/schema/ProduceBlockV4Response.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/schema/ProduceBlockV4Response.json new file mode 100644 index 00000000000..c4f1aa1edae --- /dev/null +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/schema/ProduceBlockV4Response.json @@ -0,0 +1,20 @@ +{ + "title" : "ProduceBlockV4Response", + "type" : "object", + "required" : [ "version", "execution_payload_included", "consensus_block_value" ], + "properties" : { + "version" : { + "type" : "string", + "enum" : [ "phase0", "altair", "bellatrix", "capella", "deneb", "electra", "fulu", "gloas", "heze" ] + }, + "execution_payload_included" : { + "type" : "boolean" + }, + "consensus_block_value" : { + "type" : "string", + "description" : "unsigned 256 bit integer", + "example" : "1", + "format" : "uint256" + } + } +} \ No newline at end of file diff --git a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/BeaconRestApiTypes.java b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/BeaconRestApiTypes.java index 3ad48d1feaa..9573fa6cd44 100644 --- a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/BeaconRestApiTypes.java +++ b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/BeaconRestApiTypes.java @@ -26,6 +26,7 @@ import static tech.pegasys.teku.infrastructure.http.RestApiConstants.EPOCH_QUERY_DESCRIPTION; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.GRAFFITI; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.HEADER_CONSENSUS_VERSION; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.INCLUDE_PAYLOAD; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.INDEX; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.PARAM_BLOCK_ID; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.PARAM_BLOCK_ID_DESCRIPTION; @@ -160,6 +161,15 @@ public class BeaconRestApiTypes { RestApiConstants.BUILDER_BOOST_FACTOR, UINT64_TYPE.withDescription(BUILDER_BOOST_FACTOR_DESCRIPTION)); + public static final ParameterMetadata INCLUDE_PAYLOAD_PARAMETER = + new ParameterMetadata<>( + INCLUDE_PAYLOAD, + BOOLEAN_TYPE.withDescription( + "If true, returns the execution payload envelope and blobs inline in the response " + + "(stateless mode, suitable for multi-BN setups). " + + "If false, the beacon node caches the payload for separate retrieval. " + + "Default: true.")); + public static final ParameterMetadata GRAFFITI_PARAMETER = new ParameterMetadata<>( GRAFFITI, CoreTypes.BYTES32_TYPE.withDescription("`Bytes32 Hex` Graffiti.")); diff --git a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/JsonTypeDefinitionBeaconRestApi.java b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/JsonTypeDefinitionBeaconRestApi.java index e51de4751bc..cf87a675dc7 100644 --- a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/JsonTypeDefinitionBeaconRestApi.java +++ b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/JsonTypeDefinitionBeaconRestApi.java @@ -126,6 +126,7 @@ import tech.pegasys.teku.beaconrestapi.handlers.v2.validator.GetProposerDutiesV2; import tech.pegasys.teku.beaconrestapi.handlers.v2.validator.PostAggregateAndProofsV2; import tech.pegasys.teku.beaconrestapi.handlers.v3.validator.GetNewBlockV3; +import tech.pegasys.teku.beaconrestapi.handlers.v4.validator.GetNewBlockV4; import tech.pegasys.teku.infrastructure.async.AsyncRunner; import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.events.EventChannels; @@ -299,6 +300,7 @@ private static RestApi create( .endpoint(new GetProposerDuties(dataProvider)) .endpoint(new GetProposerDutiesV2(dataProvider)) .endpoint(new GetNewBlockV3(dataProvider, schemaCache)) + .endpoint(new GetNewBlockV4(dataProvider, schemaCache)) .endpoint(new GetAttestationData(dataProvider, spec)) .endpoint(new GetAggregateAttestation(dataProvider, spec)) .endpoint(new GetAggregateAttestationV2(dataProvider, schemaCache)) diff --git a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v4/validator/GetNewBlockV4.java b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v4/validator/GetNewBlockV4.java new file mode 100644 index 00000000000..3183fb6063e --- /dev/null +++ b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v4/validator/GetNewBlockV4.java @@ -0,0 +1,125 @@ +/* + * Copyright Consensys Software Inc., 2026 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.beaconrestapi.handlers.v4.validator; + +import static tech.pegasys.teku.beaconrestapi.BeaconRestApiTypes.BUILDER_BOOST_FACTOR_PARAMETER; +import static tech.pegasys.teku.beaconrestapi.BeaconRestApiTypes.GRAFFITI_PARAMETER; +import static tech.pegasys.teku.beaconrestapi.BeaconRestApiTypes.INCLUDE_PAYLOAD_PARAMETER; +import static tech.pegasys.teku.beaconrestapi.BeaconRestApiTypes.RANDAO_PARAMETER; +import static tech.pegasys.teku.beaconrestapi.BeaconRestApiTypes.SKIP_RANDAO_VERIFICATION_PARAMETER; +import static tech.pegasys.teku.beaconrestapi.BeaconRestApiTypes.SLOT_PARAMETER; +import static tech.pegasys.teku.ethereum.json.types.EthereumTypes.ETH_CONSENSUS_HEADER_TYPE; +import static tech.pegasys.teku.ethereum.json.types.EthereumTypes.ETH_HEADER_CONSENSUS_BLOCK_VALUE_TYPE; +import static tech.pegasys.teku.ethereum.json.types.EthereumTypes.ETH_HEADER_EXECUTION_PAYLOAD_INCLUDED_TYPE; +import static tech.pegasys.teku.ethereum.json.types.EthereumTypes.MILESTONE_TYPE; +import static tech.pegasys.teku.ethereum.json.types.EthereumTypes.blockContainerAndMetaDataSszResponseType; +import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NOT_IMPLEMENTED; +import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_OK; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.CONSENSUS_BLOCK_VALUE; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.EXECUTION_PAYLOAD_INCLUDED; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.SLOT_PATH_DESCRIPTION; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.TAG_VALIDATOR; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.TAG_VALIDATOR_REQUIRED; +import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.BOOLEAN_TYPE; +import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.UINT256_TYPE; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.ArrayList; +import java.util.List; +import tech.pegasys.teku.api.DataProvider; +import tech.pegasys.teku.api.ValidatorDataProvider; +import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.json.types.SerializableTypeDefinition; +import tech.pegasys.teku.infrastructure.restapi.endpoints.AsyncApiResponse; +import tech.pegasys.teku.infrastructure.restapi.endpoints.EndpointMetadata; +import tech.pegasys.teku.infrastructure.restapi.endpoints.RestApiEndpoint; +import tech.pegasys.teku.infrastructure.restapi.endpoints.RestApiRequest; +import tech.pegasys.teku.spec.datastructures.metadata.BlockContainerAndMetaData; +import tech.pegasys.teku.spec.schemas.SchemaDefinitionCache; + +public class GetNewBlockV4 extends RestApiEndpoint { + + public static final String ROUTE = "/eth/v4/validator/blocks/{slot}"; + + protected final ValidatorDataProvider validatorDataProvider; + + public GetNewBlockV4( + final DataProvider dataProvider, final SchemaDefinitionCache schemaDefinitionCache) { + this(dataProvider.getValidatorDataProvider(), schemaDefinitionCache); + } + + public GetNewBlockV4( + final ValidatorDataProvider validatorDataProvider, + @SuppressWarnings("unused") final SchemaDefinitionCache schemaDefinitionCache) { + super(getEndpointMetaData()); + this.validatorDataProvider = validatorDataProvider; + } + + private static EndpointMetadata getEndpointMetaData() { + return EndpointMetadata.get(ROUTE) + .operationId("produceBlockV4") + .summary("Produce a new block, without signature.") + .description( + """ + Requests a beacon node to produce a valid block for post-Gloas (ePBS), which can then be signed by a validator. + Supports two operational modes controlled by `include_payload`: + + - **Stateless mode** (`include_payload=true`, default): Returns the execution payload envelope and blobs + inline, suitable for multi-BN operations. + - **Stateful mode** (`include_payload=false`): The beacon node caches the payload for separate retrieval + via `/eth/v1/validator/execution_payload_envelope/{slot}/{beacon_block_root}`. + """) + .tags(TAG_VALIDATOR, TAG_VALIDATOR_REQUIRED) + .pathParam(SLOT_PARAMETER.withDescription(SLOT_PATH_DESCRIPTION)) + .queryParamRequired(RANDAO_PARAMETER) + .queryParam(GRAFFITI_PARAMETER) + .queryParamAllowsEmpty(SKIP_RANDAO_VERIFICATION_PARAMETER) + .queryParam(BUILDER_BOOST_FACTOR_PARAMETER) + .queryParam(INCLUDE_PAYLOAD_PARAMETER) + .response( + SC_OK, + "Request successful", + getResponseType(), + blockContainerAndMetaDataSszResponseType(), + getHeaders()) + .withChainDataResponses() + .withNotImplementedResponse() + .build(); + } + + @Override + public void handleRequest(final RestApiRequest request) throws JsonProcessingException { + request.respondAsync( + SafeFuture.completedFuture( + AsyncApiResponse.respondWithError(SC_NOT_IMPLEMENTED, "Not implemented"))); + } + + private static SerializableTypeDefinition getResponseType() { + return SerializableTypeDefinition.object() + .name("ProduceBlockV4Response") + .withField("version", MILESTONE_TYPE, BlockContainerAndMetaData::specMilestone) + .withField(EXECUTION_PAYLOAD_INCLUDED, BOOLEAN_TYPE, blockContainerAndMetaData -> false) + .withField( + CONSENSUS_BLOCK_VALUE, UINT256_TYPE, BlockContainerAndMetaData::consensusBlockValue) + .build(); + } + + private static List> getHeaders() { + List> headers = new ArrayList<>(); + headers.add(ETH_CONSENSUS_HEADER_TYPE); + headers.add(ETH_HEADER_EXECUTION_PAYLOAD_INCLUDED_TYPE); + headers.add(ETH_HEADER_CONSENSUS_BLOCK_VALUE_TYPE); + return headers; + } +} diff --git a/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v4/validator/GetNewBlockV4Test.java b/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v4/validator/GetNewBlockV4Test.java new file mode 100644 index 00000000000..03b3eb89904 --- /dev/null +++ b/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v4/validator/GetNewBlockV4Test.java @@ -0,0 +1,54 @@ +/* + * Copyright Consensys Software Inc., 2026 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package tech.pegasys.teku.beaconrestapi.handlers.v4.validator; + +import static org.assertj.core.api.Assertions.assertThat; +import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NOT_IMPLEMENTED; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.RANDAO_REVEAL; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.SLOT; + +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerTest; +import tech.pegasys.teku.bls.BLSSignature; +import tech.pegasys.teku.bls.BLSTestUtil; + +public class GetNewBlockV4Test extends AbstractMigratedBeaconHandlerTest { + + private final BLSSignature signature = BLSTestUtil.randomSignature(1234); + + @BeforeEach + public void setup() { + setHandler(new GetNewBlockV4(validatorDataProvider, schemaDefinitionCache)); + request.setPathParameter(SLOT, "1"); + request.setQueryParameter(RANDAO_REVEAL, signature.toBytesCompressed().toHexString()); + } + + @Test + public void shouldReturnNotImplemented() throws JsonProcessingException { + handler.handleRequest(request); + assertThat(request.getResponseCode()).isEqualTo(SC_NOT_IMPLEMENTED); + } + + @Test + public void shouldHaveCorrectRoute() { + assertThat(GetNewBlockV4.ROUTE).isEqualTo("/eth/v4/validator/blocks/{slot}"); + } + + @Test + public void shouldHaveCorrectPath() { + assertThat(handler.getMetadata().getPath()).isEqualTo(GetNewBlockV4.ROUTE); + } +} diff --git a/ethereum/json-types/src/main/java/tech/pegasys/teku/ethereum/json/types/EthereumTypes.java b/ethereum/json-types/src/main/java/tech/pegasys/teku/ethereum/json/types/EthereumTypes.java index 5329da33982..4c08fc37910 100644 --- a/ethereum/json-types/src/main/java/tech/pegasys/teku/ethereum/json/types/EthereumTypes.java +++ b/ethereum/json-types/src/main/java/tech/pegasys/teku/ethereum/json/types/EthereumTypes.java @@ -16,6 +16,7 @@ import static tech.pegasys.teku.infrastructure.http.RestApiConstants.HEADER_CONSENSUS_BLOCK_VALUE; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.HEADER_CONSENSUS_VERSION; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.HEADER_EXECUTION_PAYLOAD_BLINDED; +import static tech.pegasys.teku.infrastructure.http.RestApiConstants.HEADER_EXECUTION_PAYLOAD_INCLUDED; import static tech.pegasys.teku.infrastructure.http.RestApiConstants.HEADER_EXECUTION_PAYLOAD_VALUE; import java.math.BigInteger; @@ -124,6 +125,12 @@ public class EthereumTypes { .required(true) .build(); + public static final BooleanHeaderTypeDefinition ETH_HEADER_EXECUTION_PAYLOAD_INCLUDED_TYPE = + new BooleanHeaderTypeDefinition( + HEADER_EXECUTION_PAYLOAD_INCLUDED, + Optional.of(true), + "Required in response so client can determine whether execution payload is included inline."); + public static final StringBasedHeaderTypeDefinition ETH_HEADER_CONSENSUS_BLOCK_VALUE_TYPE = new StringBasedHeaderTypeDefinition.Builder() diff --git a/infrastructure/http/src/main/java/tech/pegasys/teku/infrastructure/http/RestApiConstants.java b/infrastructure/http/src/main/java/tech/pegasys/teku/infrastructure/http/RestApiConstants.java index 0ed4eef59c7..05a0a55625a 100644 --- a/infrastructure/http/src/main/java/tech/pegasys/teku/infrastructure/http/RestApiConstants.java +++ b/infrastructure/http/src/main/java/tech/pegasys/teku/infrastructure/http/RestApiConstants.java @@ -166,6 +166,7 @@ public class RestApiConstants { public static final String FINALIZED = "finalized"; public static final String EXECUTION_PAYLOAD_BLINDED = "execution_payload_blinded"; public static final String EXECUTION_PAYLOAD_VALUE = "execution_payload_value"; + public static final String EXECUTION_PAYLOAD_INCLUDED = "execution_payload_included"; public static final String CONSENSUS_BLOCK_VALUE = "consensus_block_value"; public static final String TARGET_PEER_COUNT = "target_peer_count"; public static final String TARGET_PEER_COUNT_DESCRIPTION = @@ -187,6 +188,7 @@ public class RestApiConstants { "Skip verification of the `randao_reveal` value. Ignored in the Teku implementation."; public static final String BUILDER_BOOST_FACTOR = "builder_boost_factor"; + public static final String INCLUDE_PAYLOAD = "include_payload"; public static final String BUILDER_BOOST_FACTOR_DESCRIPTION = """ Percentage multiplier to apply to the builder's payload value when choosing between a @@ -223,6 +225,7 @@ then return a full (unblinded) block containing the execution node payload. public static final String HEADER_EXECUTION_PAYLOAD_BLINDED = "Eth-Execution-Payload-Blinded"; public static final String HEADER_EXECUTION_PAYLOAD_VALUE = "Eth-Execution-Payload-Value"; public static final String HEADER_CONSENSUS_BLOCK_VALUE = "Eth-Consensus-Block-Value"; + public static final String HEADER_EXECUTION_PAYLOAD_INCLUDED = "Eth-Execution-Payload-Included"; public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";