From 700435492c260eba28a72407ecf8c80e74442785 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 8 May 2024 16:34:30 +1000 Subject: [PATCH 01/11] change query param from boolean to string Signed-off-by: Gabriel Fukushima --- .../tech/pegasys/teku/beaconrestapi/BeaconRestApiTypes.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 400cd536a8a..65fa9438d60 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 @@ -141,10 +141,10 @@ public class BeaconRestApiTypes { SIGNATURE_TYPE.withDescription( "`BLSSignature Hex` BLS12-381 signature for the current epoch.")); - public static final ParameterMetadata SKIP_RANDAO_VERIFICATION_PARAMETER = + public static final ParameterMetadata SKIP_RANDAO_VERIFICATION_PARAMETER = new ParameterMetadata<>( RestApiConstants.SKIP_RANDAO_VERIFICATION, - BOOLEAN_TYPE.withDescription(SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION)); + CoreTypes.string(SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION, "true")); public static final ParameterMetadata BUILDER_BOOST_FACTOR_PARAMETER = new ParameterMetadata<>( From daeabe1c879dc8fe8b10f0d9b1d623489c5aa3d4 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 8 May 2024 16:34:36 +1000 Subject: [PATCH 02/11] fix test Signed-off-by: Gabriel Fukushima --- .../beacon/paths/_eth_v3_validator_blocks_{slot}.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json index 0ee02a55cc5..722712c954f 100644 --- a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json @@ -37,8 +37,9 @@ "name" : "skip_randao_verification", "in" : "query", "schema" : { - "type" : "boolean", - "description" : "Skip verification of the `randao_reveal` value. If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value" + "type": "string", + "description" : "Skip verification of the `randao_reveal` value. If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value", + "example": "true" } }, { "name" : "builder_boost_factor", From 35600b55c44174240bb710fc14665869f14dd15c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 27 May 2024 17:32:25 +1000 Subject: [PATCH 03/11] Add flag style string query parameter Signed-off-by: Gabriel Fukushima --- .../beaconrestapi/BeaconRestApiTypes.java | 2 +- .../infrastructure/json/types/CoreTypes.java | 10 ++++ .../StringBasedPrimitiveTypeDefinition.java | 49 +++++++++++++++++-- 3 files changed, 55 insertions(+), 6 deletions(-) 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 65fa9438d60..777e00fcdac 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 @@ -144,7 +144,7 @@ public class BeaconRestApiTypes { public static final ParameterMetadata SKIP_RANDAO_VERIFICATION_PARAMETER = new ParameterMetadata<>( RestApiConstants.SKIP_RANDAO_VERIFICATION, - CoreTypes.string(SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION, "true")); + CoreTypes.flag(SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION, "")); public static final ParameterMetadata BUILDER_BOOST_FACTOR_PARAMETER = new ParameterMetadata<>( diff --git a/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java b/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java index 179ac721a9f..085abe67afe 100644 --- a/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java +++ b/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java @@ -114,6 +114,16 @@ public static StringValueTypeDefinition string( return stringBuilder().description(description).example(example).build(); } + public static StringValueTypeDefinition flag( + final String description, final String example) { + return stringBuilder() + .description(description) + .example(example) + .minLength(0) + .maxLength(0) + .build(); + } + private static StringTypeBuilder stringBuilder() { return DeserializableTypeDefinition.string(String.class) .formatter(Function.identity()) diff --git a/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/StringBasedPrimitiveTypeDefinition.java b/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/StringBasedPrimitiveTypeDefinition.java index f712a03490c..dace7aab911 100644 --- a/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/StringBasedPrimitiveTypeDefinition.java +++ b/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/StringBasedPrimitiveTypeDefinition.java @@ -34,6 +34,8 @@ public class StringBasedPrimitiveTypeDefinition implements StringValueTypeDef private final Optional example; private final Optional format; private final Optional pattern; + private final Optional minLength; + private final Optional maxLength; private StringBasedPrimitiveTypeDefinition( final Optional name, @@ -43,7 +45,9 @@ private StringBasedPrimitiveTypeDefinition( final Optional example, final Optional description, final Optional format, - final Optional pattern) { + final Optional pattern, + final Optional minLength, + final Optional maxLength) { this.name = name; this.title = title; this.objectFromString = objectFromString; @@ -52,6 +56,8 @@ private StringBasedPrimitiveTypeDefinition( this.description = description; this.format = format; this.pattern = pattern; + this.minLength = minLength; + this.maxLength = maxLength; } @Override @@ -78,7 +84,9 @@ public StringValueTypeDefinition withDescription(final String description) { example, Optional.of(description), format, - pattern); + pattern, + minLength, + maxLength); } @Override @@ -105,6 +113,12 @@ public void serializeOpenApiType(final JsonGenerator gen) throws IOException { if (format.isPresent()) { gen.writeStringField("format", format.get()); } + if (minLength.isPresent()) { + gen.writeNumberField("minLength", minLength.get()); + } + if (maxLength.isPresent()) { + gen.writeNumberField("maxLength", maxLength.get()); + } gen.writeEndObject(); } @@ -117,6 +131,8 @@ public String toString() { .add("example", example) .add("format", format) .add("pattern", pattern) + .add("minLength", minLength) + .add("maxLength", maxLength) .toString(); } @@ -144,6 +160,8 @@ public static class StringTypeBuilder { private Optional description = Optional.empty(); private Optional format = Optional.empty(); private Optional pattern = Optional.empty(); + private Optional minLength = Optional.empty(); + private Optional maxLength = Optional.empty(); public StringTypeBuilder name(final String name) { this.name = Optional.of(name); @@ -185,12 +203,31 @@ public StringTypeBuilder pattern(final String pattern) { return this; } + public StringTypeBuilder minLength(final int minLength) { + this.minLength = Optional.of(minLength); + return this; + } + + public StringTypeBuilder maxLength(final int maxLength) { + this.maxLength = Optional.of(maxLength); + return this; + } + public StringValueTypeDefinition build() { checkNotNull(parser, "Must specify parser"); checkNotNull(formatter, "Must specify formatter"); return new StringBasedPrimitiveTypeDefinition<>( - name, title.or(() -> name), parser, formatter, example, description, format, pattern); + name, + title.or(() -> name), + parser, + formatter, + example, + description, + format, + pattern, + minLength, + maxLength); } } @@ -208,11 +245,13 @@ public boolean equals(final Object o) { && Objects.equals(description, that.description) && Objects.equals(example, that.example) && Objects.equals(format, that.format) - && Objects.equals(pattern, that.pattern); + && Objects.equals(pattern, that.pattern) + && Objects.equals(minLength, that.minLength) + && Objects.equals(maxLength, that.maxLength); } @Override public int hashCode() { - return Objects.hash(name, title, description, example, format, pattern); + return Objects.hash(name, title, description, example, format, pattern, minLength, maxLength); } } From 0fa52b19eb08849960cb420c5b1f2659fe915ecb Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 27 May 2024 17:32:56 +1000 Subject: [PATCH 04/11] Add queryParams that explicitly allow empty values Signed-off-by: Gabriel Fukushima --- .../handlers/v3/validator/GetNewBlockV3.java | 2 +- .../restapi/endpoints/EndpointMetadata.java | 46 ++++++++++++++++--- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3.java b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3.java index 9c4ffb2f690..5c7589ce08d 100644 --- a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3.java +++ b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v3/validator/GetNewBlockV3.java @@ -95,7 +95,7 @@ private static EndpointMetadata getEndpointMetaData( .pathParam(SLOT_PARAMETER.withDescription(SLOT_PATH_DESCRIPTION)) .queryParamRequired(RANDAO_PARAMETER) .queryParam(GRAFFITI_PARAMETER) - .queryParam(SKIP_RANDAO_VERIFICATION_PARAMETER) + .queryParamAllowsEmpty(SKIP_RANDAO_VERIFICATION_PARAMETER) .queryParam(BUILDER_BOOST_FACTOR_PARAMETER) .response( SC_OK, diff --git a/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java b/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java index a23a25b1254..c72e0ebf2f6 100644 --- a/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java +++ b/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java @@ -85,6 +85,7 @@ public class EndpointMetadata { private final Map> pathParams; private final Map> requiredQueryParams; private final Map> queryParams; + private final Map> queryParamsAllowEmpty; private final Map> queryListParams; private final Map> requiredHeaders; private final Map> headers; @@ -105,6 +106,7 @@ private EndpointMetadata( final List tags, final Map> pathParams, final Map> queryParams, + final Map> queryParamsAllowEmpty, final Map> requiredQueryParams, final Map> queryListParams, final Map> requiredHeaders, @@ -124,6 +126,7 @@ private EndpointMetadata( this.tags = tags; this.pathParams = pathParams; this.queryParams = queryParams; + this.queryParamsAllowEmpty = queryParamsAllowEmpty; this.requiredQueryParams = requiredQueryParams; this.queryListParams = queryListParams; this.requiredHeaders = requiredHeaders; @@ -223,12 +226,15 @@ public StringValueTypeDefinition getQueryParameterDefinition(final String par checkArgument( requiredQueryParams.containsKey(parameterName) || queryParams.containsKey(parameterName) + || queryParamsAllowEmpty.containsKey(parameterName) || queryListParams.containsKey(parameterName), "Query parameter " + parameterName + " was not found in endpoint metadata"); if (requiredQueryParams.containsKey(parameterName)) { return requiredQueryParams.get(parameterName); } else if (queryParams.containsKey(parameterName)) { return queryParams.get(parameterName); + } else if (queryParamsAllowEmpty.containsKey(parameterName)) { + return queryParamsAllowEmpty.get(parameterName); } return queryListParams.get(parameterName); @@ -310,17 +316,19 @@ public void writeOpenApi(final JsonGenerator gen) throws IOException { } if (pathParams.size() > 0 || queryParams.size() > 0 + || queryParamsAllowEmpty.size() > 0 || requiredQueryParams.size() > 0 || queryListParams.size() > 0 || requiredHeaders.size() > 0 || headers.size() > 0) { gen.writeArrayFieldStart("parameters"); - writeParameters(gen, pathParams, "path", true, false); - writeParameters(gen, requiredQueryParams, "query", true, false); - writeParameters(gen, queryParams, "query", false, false); - writeParameters(gen, queryListParams, "query", false, true); - writeParameters(gen, requiredHeaders, "header", true, false); - writeParameters(gen, headers, "header", false, false); + writeParameters(gen, pathParams, "path", true, false, false); + writeParameters(gen, requiredQueryParams, "query", true, false, false); + writeParameters(gen, queryParams, "query", false, false, false); + writeParameters(gen, queryParamsAllowEmpty, "query", false, false, true); + writeParameters(gen, queryListParams, "query", false, true, false); + writeParameters(gen, requiredHeaders, "header", true, false, false); + writeParameters(gen, headers, "header", false, false, false); gen.writeEndArray(); } @@ -364,7 +372,8 @@ private void writeParameters( final Map> fields, final String parameterUsedIn, final boolean isMandatoryField, - final boolean isList) + final boolean isList, + final boolean allowEmptyValue) throws IOException { for (Map.Entry> entry : fields.entrySet()) { gen.writeStartObject(); @@ -372,6 +381,9 @@ private void writeParameters( if (isMandatoryField) { gen.writeObjectField("required", true); } + if (allowEmptyValue) { + gen.writeObjectField("allowEmptyValue", true); + } gen.writeObjectField("in", parameterUsedIn); gen.writeFieldName("schema"); if (isList) { // Handle list parameter @@ -384,6 +396,7 @@ private void writeParameters( } else { // Handle regular parameter entry.getValue().serializeOpenApiTypeOrReference(gen); } + gen.writeEndObject(); } } @@ -430,6 +443,8 @@ public static class EndpointMetaDataBuilder { private boolean requiredRequestBody = true; private final Map> pathParams = new LinkedHashMap<>(); private final Map> queryParams = new LinkedHashMap<>(); + private final Map> queryParamsAllowEmpty = + new LinkedHashMap<>(); private final Map> requiredQueryParams = new LinkedHashMap<>(); private final Map> queryListParams = new LinkedHashMap<>(); @@ -465,6 +480,7 @@ public EndpointMetaDataBuilder pathParam(final ParameterMetadata parameterMet public EndpointMetaDataBuilder queryParam(final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); if (queryParams.containsKey(param) + || queryParamsAllowEmpty.containsKey(param) || requiredQueryParams.containsKey(param) || queryListParams.containsKey(param)) { throw new IllegalStateException("Query parameters already contains " + param); @@ -473,10 +489,24 @@ public EndpointMetaDataBuilder queryParam(final ParameterMetadata parameterMe return this; } + public EndpointMetaDataBuilder queryParamAllowsEmpty( + final ParameterMetadata parameterMetadata) { + final String param = parameterMetadata.getName(); + if (queryParams.containsKey(param) + || queryParamsAllowEmpty.containsKey(param) + || requiredQueryParams.containsKey(param) + || queryListParams.containsKey(param)) { + throw new IllegalStateException("Query parameters already contains " + param); + } + queryParamsAllowEmpty.put(parameterMetadata.getName(), parameterMetadata.getType()); + return this; + } + public EndpointMetaDataBuilder queryParamRequired( final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); if (queryParams.containsKey(param) + || queryParamsAllowEmpty.containsKey(param) || requiredQueryParams.containsKey(param) || queryListParams.containsKey(param)) { throw new IllegalStateException("Query parameters already contains " + param); @@ -488,6 +518,7 @@ public EndpointMetaDataBuilder queryParamRequired( public EndpointMetaDataBuilder queryListParam(final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); if (queryParams.containsKey(param) + || queryParamsAllowEmpty.containsKey(param) || requiredQueryParams.containsKey(param) || queryListParams.containsKey(param)) { throw new IllegalStateException("Query parameters already contains " + param); @@ -752,6 +783,7 @@ public EndpointMetadata build() { tags, pathParams, queryParams, + queryParamsAllowEmpty, requiredQueryParams, queryListParams, requiredHeaders, From 3401cffb5eec81ec277b0b12fee4e1806f68dd16 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 27 May 2024 18:17:29 +1000 Subject: [PATCH 05/11] adjust test Signed-off-by: Gabriel Fukushima --- .../beacon/paths/_eth_v3_validator_blocks_{slot}.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json index 722712c954f..4d67b131b52 100644 --- a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json @@ -35,11 +35,14 @@ } }, { "name" : "skip_randao_verification", + "allowEmptyValue" : true, "in" : "query", "schema" : { - "type": "string", + "type" : "string", "description" : "Skip verification of the `randao_reveal` value. If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value", - "example": "true" + "example" : "", + "minLength" : 0, + "maxLength" : 0 } }, { "name" : "builder_boost_factor", From 6ec7d3227ef0bf7c77ab5f900688fbb134cdfc2a Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 27 May 2024 18:17:46 +1000 Subject: [PATCH 06/11] remove example Signed-off-by: Gabriel Fukushima --- .../pegasys/teku/beaconrestapi/BeaconRestApiTypes.java | 2 +- .../teku/infrastructure/json/types/CoreTypes.java | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) 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 777e00fcdac..8fc454f72ec 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 @@ -144,7 +144,7 @@ public class BeaconRestApiTypes { public static final ParameterMetadata SKIP_RANDAO_VERIFICATION_PARAMETER = new ParameterMetadata<>( RestApiConstants.SKIP_RANDAO_VERIFICATION, - CoreTypes.flag(SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION, "")); + CoreTypes.flag(SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION)); public static final ParameterMetadata BUILDER_BOOST_FACTOR_PARAMETER = new ParameterMetadata<>( diff --git a/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java b/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java index 085abe67afe..f3837f07cd8 100644 --- a/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java +++ b/infrastructure/json/src/main/java/tech/pegasys/teku/infrastructure/json/types/CoreTypes.java @@ -114,14 +114,8 @@ public static StringValueTypeDefinition string( return stringBuilder().description(description).example(example).build(); } - public static StringValueTypeDefinition flag( - final String description, final String example) { - return stringBuilder() - .description(description) - .example(example) - .minLength(0) - .maxLength(0) - .build(); + public static StringValueTypeDefinition flag(final String description) { + return stringBuilder().description(description).minLength(0).maxLength(0).build(); } private static StringTypeBuilder stringBuilder() { From 12e172d227af0c7387d41955f348257abc9c4b67 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 27 May 2024 18:25:37 +1000 Subject: [PATCH 07/11] fix test Signed-off-by: Gabriel Fukushima --- .../_eth_v3_validator_blocks_{slot}.json | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json index 4d67b131b52..0704ba46328 100644 --- a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json @@ -34,25 +34,24 @@ "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" : "skip_randao_verification", "allowEmptyValue" : true, "in" : "query", "schema" : { "type" : "string", "description" : "Skip verification of the `randao_reveal` value. If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value", - "example" : "", "minLength" : 0, "maxLength" : 0 } - }, { - "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" - } } ], "responses" : { "200" : { From 73cfe23c91e31af832f20491b48255c35a83c8ca Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 29 May 2024 11:10:24 +1000 Subject: [PATCH 08/11] extract validation into separate method Signed-off-by: Gabriel Fukushima --- .../restapi/endpoints/EndpointMetadata.java | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java b/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java index c72e0ebf2f6..9d3b87983c4 100644 --- a/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java +++ b/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java @@ -479,10 +479,7 @@ public EndpointMetaDataBuilder pathParam(final ParameterMetadata parameterMet public EndpointMetaDataBuilder queryParam(final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); - if (queryParams.containsKey(param) - || queryParamsAllowEmpty.containsKey(param) - || requiredQueryParams.containsKey(param) - || queryListParams.containsKey(param)) { + if (queryParamAlreadyAdded(param)) { throw new IllegalStateException("Query parameters already contains " + param); } queryParams.put(parameterMetadata.getName(), parameterMetadata.getType()); @@ -492,10 +489,7 @@ public EndpointMetaDataBuilder queryParam(final ParameterMetadata parameterMe public EndpointMetaDataBuilder queryParamAllowsEmpty( final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); - if (queryParams.containsKey(param) - || queryParamsAllowEmpty.containsKey(param) - || requiredQueryParams.containsKey(param) - || queryListParams.containsKey(param)) { + if (queryParamAlreadyAdded(param)) { throw new IllegalStateException("Query parameters already contains " + param); } queryParamsAllowEmpty.put(parameterMetadata.getName(), parameterMetadata.getType()); @@ -505,10 +499,7 @@ public EndpointMetaDataBuilder queryParamAllowsEmpty( public EndpointMetaDataBuilder queryParamRequired( final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); - if (queryParams.containsKey(param) - || queryParamsAllowEmpty.containsKey(param) - || requiredQueryParams.containsKey(param) - || queryListParams.containsKey(param)) { + if (queryParamAlreadyAdded(param)) { throw new IllegalStateException("Query parameters already contains " + param); } requiredQueryParams.put(parameterMetadata.getName(), parameterMetadata.getType()); @@ -517,16 +508,20 @@ public EndpointMetaDataBuilder queryParamRequired( public EndpointMetaDataBuilder queryListParam(final ParameterMetadata parameterMetadata) { final String param = parameterMetadata.getName(); - if (queryParams.containsKey(param) - || queryParamsAllowEmpty.containsKey(param) - || requiredQueryParams.containsKey(param) - || queryListParams.containsKey(param)) { + if (queryParamAlreadyAdded(param)) { throw new IllegalStateException("Query parameters already contains " + param); } queryListParams.put(parameterMetadata.getName(), parameterMetadata.getType()); return this; } + private boolean queryParamAlreadyAdded(final String param) { + return queryParams.containsKey(param) + || queryParamsAllowEmpty.containsKey(param) + || requiredQueryParams.containsKey(param) + || queryListParams.containsKey(param); + } + public EndpointMetaDataBuilder headerRequired(final ParameterMetadata headerMetadata) { checkRequestHeader(headerMetadata); requiredHeaders.put(headerMetadata.getName(), headerMetadata.getType()); From 035b2481154e02f126c3363f86edc8e779d2dedb Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 29 May 2024 11:13:59 +1000 Subject: [PATCH 09/11] apply intelliJ suggestion Signed-off-by: Gabriel Fukushima --- .../restapi/endpoints/EndpointMetadata.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java b/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java index 9d3b87983c4..53a3344c18b 100644 --- a/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java +++ b/infrastructure/restapi/src/main/java/tech/pegasys/teku/infrastructure/restapi/endpoints/EndpointMetadata.java @@ -314,13 +314,13 @@ public void writeOpenApi(final JsonGenerator gen) throws IOException { if (deprecated) { gen.writeBooleanField("deprecated", true); } - if (pathParams.size() > 0 - || queryParams.size() > 0 - || queryParamsAllowEmpty.size() > 0 - || requiredQueryParams.size() > 0 - || queryListParams.size() > 0 - || requiredHeaders.size() > 0 - || headers.size() > 0) { + if (!pathParams.isEmpty() + || !queryParams.isEmpty() + || !queryParamsAllowEmpty.isEmpty() + || !requiredQueryParams.isEmpty() + || !queryListParams.isEmpty() + || !requiredHeaders.isEmpty() + || !headers.isEmpty()) { gen.writeArrayFieldStart("parameters"); writeParameters(gen, pathParams, "path", true, false, false); writeParameters(gen, requiredQueryParams, "query", true, false, false); From 8f29351105c001bc04ddcde0203b7a65c3446b5f Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Thu, 30 May 2024 14:45:25 +1000 Subject: [PATCH 10/11] Change skip_randao_verification description to inform that flag is currently ignored by impl Signed-off-by: Gabriel Fukushima --- .../beacon/paths/_eth_v3_validator_blocks_{slot}.json | 2 +- .../tech/pegasys/teku/infrastructure/http/RestApiConstants.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json index 0704ba46328..7b43f950d36 100644 --- a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json @@ -48,7 +48,7 @@ "in" : "query", "schema" : { "type" : "string", - "description" : "Skip verification of the `randao_reveal` value. If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value", + "description" : "Skip verification of the `randao_reveal` value (currently ignored by Teku implementation). If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value", "minLength" : 0, "maxLength" : 0 } 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 c07df153f1b..1e7bca66997 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 @@ -183,7 +183,7 @@ public class RestApiConstants { + SC_SERVICE_UNAVAILABLE + " status code if set to true and no validators have been registered with the builder"; public static final String SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION = - "Skip verification of the `randao_reveal` value. If this flag is set then the\n" + "Skip verification of the `randao_reveal` value (currently ignored by Teku implementation). If this flag is set then the\n" + " `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n" + " is a flag and does not take a value"; From 52fdec6b74cba2626e025b696808d64e11c8bad9 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 31 May 2024 14:28:42 +1000 Subject: [PATCH 11/11] Change skip_randao_verification param description to clarify teku doesn't use it Signed-off-by: Gabriel Fukushima --- .../beacon/paths/_eth_v3_validator_blocks_{slot}.json | 2 +- .../pegasys/teku/infrastructure/http/RestApiConstants.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json index 7b43f950d36..a24409c5cb1 100644 --- a/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json +++ b/data/beaconrestapi/src/integration-test/resources/tech/pegasys/teku/beaconrestapi/beacon/paths/_eth_v3_validator_blocks_{slot}.json @@ -48,7 +48,7 @@ "in" : "query", "schema" : { "type" : "string", - "description" : "Skip verification of the `randao_reveal` value (currently ignored by Teku implementation). If this flag is set then the\n `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n is a flag and does not take a value", + "description" : "Skip verification of the `randao_reveal` value. Ignored in the Teku implementation.", "minLength" : 0, "maxLength" : 0 } 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 1e7bca66997..b0d2c235463 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 @@ -183,9 +183,7 @@ public class RestApiConstants { + SC_SERVICE_UNAVAILABLE + " status code if set to true and no validators have been registered with the builder"; public static final String SKIP_RANDAO_VERIFICATION_PARAM_DESCRIPTION = - "Skip verification of the `randao_reveal` value (currently ignored by Teku implementation). If this flag is set then the\n" - + " `randao_reveal` must be set to the point at infinity (`0xc0..00`). This query parameter\n" - + " is a flag and does not take a value"; + "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 BUILDER_BOOST_FACTOR_DESCRIPTION =