Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Breaking Changes

### Additions and Improvements
- Added ssz output for validator balances api.

### Bug Fixes
- Updated Libp2p to remove handshake info message.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
"schema" : {
"$ref" : "#/components/schemas/GetStateValidatorBalancesResponse"
}
},
"application/octet-stream" : {
"schema" : {
"type" : "string",
"format" : "binary"
}
}
}
},
Expand All @@ -45,6 +51,16 @@
}
}
},
"406" : {
"description" : "Not acceptable",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/HttpErrorResponse"
}
}
}
},
"503" : {
"description" : "Service unavailable",
"content" : {
Expand Down Expand Up @@ -117,6 +133,12 @@
"schema" : {
"$ref" : "#/components/schemas/GetStateValidatorBalancesResponse"
}
},
"application/octet-stream" : {
"schema" : {
"type" : "string",
"format" : "binary"
}
}
}
},
Expand All @@ -130,6 +152,16 @@
}
}
},
"406" : {
"description" : "Not acceptable",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/HttpErrorResponse"
}
}
}
},
"503" : {
"description" : "Service unavailable",
"content" : {
Expand Down Expand Up @@ -166,4 +198,4 @@
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,8 @@
"data" : {
"type" : "array",
"items" : {
"type" : "object",
"required" : [ "index", "balance" ],
"properties" : {
"index" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"example" : "1",
"format" : "uint64"
},
"balance" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"example" : "1",
"format" : "uint64"
}
}
"$ref" : "#/components/schemas/ValidatorBalanceResponse"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"title" : "ValidatorBalanceResponse",
"type" : "object",
"required" : [ "index", "balance" ],
"properties" : {
"index" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"example" : "1",
"format" : "uint64"
},
"balance" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"example" : "1",
"format" : "uint64"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,36 @@
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.FINALIZED;
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.TAG_BEACON;
import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.BOOLEAN_TYPE;
import static tech.pegasys.teku.infrastructure.json.types.SerializableTypeDefinition.listOf;

import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.List;
import java.util.Optional;
import tech.pegasys.teku.api.ChainDataProvider;
import tech.pegasys.teku.api.DataProvider;
import tech.pegasys.teku.api.migrated.StateValidatorBalanceData;
import tech.pegasys.teku.ethereum.json.types.EthereumTypes;
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.infrastructure.ssz.SszList;
import tech.pegasys.teku.spec.datastructures.metadata.ObjectAndMetaData;
import tech.pegasys.teku.spec.schemas.api.StateValidatorBalanceData;

public class GetStateValidatorBalances extends RestApiEndpoint {
public static final String ROUTE = "/eth/v1/beacon/states/{state_id}/validator_balances";

static final SerializableTypeDefinition<ObjectAndMetaData<List<StateValidatorBalanceData>>>
static final SerializableTypeDefinition<ObjectAndMetaData<SszList<StateValidatorBalanceData>>>
RESPONSE_TYPE =
SerializableTypeDefinition.<ObjectAndMetaData<List<StateValidatorBalanceData>>>object()
SerializableTypeDefinition.<ObjectAndMetaData<SszList<StateValidatorBalanceData>>>object()
.name("GetStateValidatorBalancesResponse")
.withField(
EXECUTION_OPTIMISTIC, BOOLEAN_TYPE, ObjectAndMetaData::isExecutionOptimistic)
.withField(FINALIZED, BOOLEAN_TYPE, ObjectAndMetaData::isFinalized)
.withField(
"data",
listOf(StateValidatorBalanceData.getJsonTypeDefinition()),
StateValidatorBalanceData.SSZ_LIST_SCHEMA.getJsonTypeDefinition(),
ObjectAndMetaData::getData)
.build();

Expand All @@ -67,8 +68,9 @@ public GetStateValidatorBalances(final DataProvider dataProvider) {
.tags(TAG_BEACON)
.pathParam(PARAMETER_STATE_ID)
.queryListParam(ID_PARAMETER)
.response(SC_OK, "Request successful", RESPONSE_TYPE)
.response(SC_OK, "Request successful", RESPONSE_TYPE, EthereumTypes.sszResponseType())
.withNotFoundResponse()
.withNotAcceptableResponse()
.withChainDataResponses()
.build());
this.chainDataProvider = chainDataProvider;
Expand All @@ -78,7 +80,7 @@ public GetStateValidatorBalances(final DataProvider dataProvider) {
public void handleRequest(final RestApiRequest request) throws JsonProcessingException {
final List<String> validators = request.getQueryParameterList(ID_PARAMETER);

final SafeFuture<Optional<ObjectAndMetaData<List<StateValidatorBalanceData>>>> future =
final SafeFuture<Optional<ObjectAndMetaData<SszList<StateValidatorBalanceData>>>> future =
chainDataProvider.getStateValidatorBalances(
request.getPathParameter(PARAMETER_STATE_ID), validators);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@
import java.util.Optional;
import tech.pegasys.teku.api.ChainDataProvider;
import tech.pegasys.teku.api.DataProvider;
import tech.pegasys.teku.api.migrated.StateValidatorBalanceData;
import tech.pegasys.teku.ethereum.json.types.EthereumTypes;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.json.types.DeserializableTypeDefinition;
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.infrastructure.ssz.SszList;
import tech.pegasys.teku.spec.datastructures.metadata.ObjectAndMetaData;
import tech.pegasys.teku.spec.schemas.api.StateValidatorBalanceData;

public class PostStateValidatorBalances extends RestApiEndpoint {
private final ChainDataProvider chainDataProvider;
Expand All @@ -49,8 +51,13 @@ public PostStateValidatorBalances(final DataProvider dataProvider) {
.pathParam(PARAMETER_STATE_ID)
.optionalRequestBody()
.requestBodyType(DeserializableTypeDefinition.listOf(STRING_TYPE))
.response(SC_OK, "Request successful", GetStateValidatorBalances.RESPONSE_TYPE)
.response(
SC_OK,
"Request successful",
GetStateValidatorBalances.RESPONSE_TYPE,
EthereumTypes.sszResponseType())
.withNotFoundResponse()
.withNotAcceptableResponse()
.withChainDataResponses()
.build());
this.chainDataProvider = chainDataProvider;
Expand All @@ -60,7 +67,7 @@ public PostStateValidatorBalances(final DataProvider dataProvider) {
public void handleRequest(final RestApiRequest request) throws JsonProcessingException {
final Optional<List<String>> validators = request.getOptionalRequestBody();

final SafeFuture<Optional<ObjectAndMetaData<List<StateValidatorBalanceData>>>> future =
final SafeFuture<Optional<ObjectAndMetaData<SszList<StateValidatorBalanceData>>>> future =
chainDataProvider.getStateValidatorBalances(
request.getPathParameter(PARAMETER_STATE_ID), validators.orElse(List.of()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_BAD_REQUEST;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_INTERNAL_SERVER_ERROR;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NOT_ACCEPTABLE;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NOT_FOUND;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NO_CONTENT;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_OK;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_SERVICE_UNAVAILABLE;
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.getResponseSszFromMetadata;
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.getResponseStringFromMetadata;
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.verifyMetadataEmptyResponse;
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.verifyMetadataErrorResponse;
Expand All @@ -31,14 +33,16 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.api.migrated.StateValidatorBalanceData;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerWithChainDataProviderTest;
import tech.pegasys.teku.infrastructure.restapi.StubRestApiRequest;
import tech.pegasys.teku.infrastructure.ssz.SszList;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.metadata.ObjectAndMetaData;
import tech.pegasys.teku.spec.schemas.api.StateValidatorBalanceData;

public class GetStateValidatorBalancesTest
extends AbstractMigratedBeaconHandlerWithChainDataProviderTest {
Expand All @@ -60,8 +64,9 @@ public void shouldGetSpecifiedValidatorBalancesFromState() throws Exception {
.listQueryParameter("id", List.of("1", "2"))
.build();

final Optional<ObjectAndMetaData<List<StateValidatorBalanceData>>> stateValidatorBalancesData =
chainDataProvider.getStateValidatorBalances("head", List.of("1", "2")).get();
final Optional<ObjectAndMetaData<SszList<StateValidatorBalanceData>>>
stateValidatorBalancesData =
chainDataProvider.getStateValidatorBalances("head", List.of("1", "2")).get();

handler.handleRequest(request);

Expand All @@ -77,8 +82,9 @@ public void shouldGetAllValidatorBalancesFromState() throws Exception {
.pathParameter("state_id", "head")
.build();

final Optional<ObjectAndMetaData<List<StateValidatorBalanceData>>> stateValidatorBalancesData =
chainDataProvider.getStateValidatorBalances("head", List.of()).get();
final Optional<ObjectAndMetaData<SszList<StateValidatorBalanceData>>>
stateValidatorBalancesData =
chainDataProvider.getStateValidatorBalances("head", List.of()).get();

handler.handleRequest(request);

Expand All @@ -96,20 +102,21 @@ void metadata_shouldHandle404() throws JsonProcessingException {
verifyMetadataErrorResponse(handler, SC_NOT_FOUND);
}

@Test
void metadata_shouldHandle406() throws JsonProcessingException {
verifyMetadataErrorResponse(handler, SC_NOT_ACCEPTABLE);
}

@Test
void metadata_shouldHandle500() throws JsonProcessingException {
verifyMetadataErrorResponse(handler, SC_INTERNAL_SERVER_ERROR);
}

@Test
void metadata_shouldHandle200() throws IOException {
List<StateValidatorBalanceData> stateValidatorBalanceData = new ArrayList<>();
for (int i = 0; i < 10; i++) {
stateValidatorBalanceData.add(
new StateValidatorBalanceData(UInt64.valueOf(i), dataStructureUtil.randomUInt64()));
}
SszList<StateValidatorBalanceData> stateValidatorBalanceData = getValidatorBalanceList(10);

ObjectAndMetaData<List<StateValidatorBalanceData>> responseData =
ObjectAndMetaData<SszList<StateValidatorBalanceData>> responseData =
withMetaData(stateValidatorBalanceData);

final String data = getResponseStringFromMetadata(handler, SC_OK, responseData);
Expand All @@ -121,6 +128,27 @@ void metadata_shouldHandle200() throws IOException {
assertThat(data).isEqualTo(expected);
}

@Test
void metadata_shouldHandle200OctetStream() throws JsonProcessingException {
SszList<StateValidatorBalanceData> stateValidatorBalanceData = getValidatorBalanceList(2);

ObjectAndMetaData<SszList<StateValidatorBalanceData>> responseData =
withMetaData(stateValidatorBalanceData);

final byte[] data = getResponseSszFromMetadata(handler, SC_OK, responseData);

assertThat(Bytes.of(data)).isEqualTo(stateValidatorBalanceData.sszSerialize());
}

private SszList<StateValidatorBalanceData> getValidatorBalanceList(final int count) {
List<StateValidatorBalanceData> stateValidatorBalanceData = new ArrayList<>();
for (int i = 0; i < count; i++) {
stateValidatorBalanceData.add(
new StateValidatorBalanceData(UInt64.valueOf(i), dataStructureUtil.randomUInt64()));
}
return StateValidatorBalanceData.SSZ_LIST_SCHEMA.createFromElements(stateValidatorBalanceData);
}

@Test
void metadata_shouldHandle204() {
verifyMetadataEmptyResponse(handler, SC_NO_CONTENT);
Expand Down
Loading
Loading