diff --git a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChanges.java b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChanges.java index 06f0057fa15..12c17034911 100644 --- a/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChanges.java +++ b/data/beaconrestapi/src/main/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChanges.java @@ -36,6 +36,7 @@ public class PostBlsToExecutionChanges extends RestApiEndpoint { public static final String ROUTE = "/eth/v1/beacon/pool/bls_to_execution_changes"; + private static final int MAX_BLS_MESSAGES_PER_REQUEST = 5000; private final NodeDataProvider nodeDataProvider; public PostBlsToExecutionChanges( @@ -76,6 +77,15 @@ private static EndpointMetadata createEndpointMetadata(final SchemaDefinitionCac @Override public void handleRequest(RestApiRequest request) throws JsonProcessingException { final List blsToExecutionChanges = request.getRequestBody(); + if (blsToExecutionChanges.size() > MAX_BLS_MESSAGES_PER_REQUEST) { + final String errorMessage = + String.format( + "A maximum of %s SignedBLSToExecutionChange objects can be submitted to the node's pool at one time", + MAX_BLS_MESSAGES_PER_REQUEST); + request.respondError(SC_BAD_REQUEST, errorMessage); + return; + } + final SafeFuture> future = nodeDataProvider.postBlsToExecutionChanges(blsToExecutionChanges); diff --git a/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChangesTest.java b/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChangesTest.java index 8c7d0c5a2ce..8ec03f0a819 100644 --- a/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChangesTest.java +++ b/data/beaconrestapi/src/test/java/tech/pegasys/teku/beaconrestapi/handlers/v1/beacon/PostBlsToExecutionChangesTest.java @@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.io.Resources; import java.io.IOException; +import java.util.Collections; import java.util.List; import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.BeforeEach; @@ -36,6 +37,7 @@ import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerTest; import tech.pegasys.teku.beaconrestapi.schema.ErrorListBadRequest; import tech.pegasys.teku.infrastructure.async.SafeFuture; +import tech.pegasys.teku.infrastructure.http.HttpErrorResponse; import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.spec.SpecMilestone; import tech.pegasys.teku.spec.TestSpecFactory; @@ -90,6 +92,23 @@ void shouldReturnBadRequestWhenInvalidOperationIsSubmittedToThePool() throws Exc assertThat(request.getResponseBody()).isEqualTo(expectedBody); } + @Test + void shouldReturnBadRequestWhenInvalidNumberOfOperationsSubmitted() throws Exception { + final SignedBlsToExecutionChange blsToExecutionChange = + dataStructureUtil.randomSignedBlsToExecutionChange(); + List requestBody = Collections.nCopies(5001, blsToExecutionChange); + + request.setRequestBody(requestBody); + handler.handleRequest(request); + + assertThat(request.getResponseCode()).isEqualTo(SC_BAD_REQUEST); + assertThat(request.getResponseBody()) + .isEqualTo( + new HttpErrorResponse( + SC_BAD_REQUEST, + "A maximum of 5000 SignedBLSToExecutionChange objects can be submitted to the node's pool at one time")); + } + @Test void metadata_shouldHandle400() throws IOException { final List errors =