Skip to content

Commit

Permalink
Create getBlockRewardsFromBlockId method in ChainDataProvider (#7024)
Browse files Browse the repository at this point in the history
  • Loading branch information
courtneyeh authored May 2, 2023
1 parent c4783a7 commit 4d42661
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 136 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ For information on changes in released versions of Teku, see the [releases page]
### Additions and Improvements
- Set `User-Agent` header to "teku/v<version>" (e.g. teku/v23.4.0) when making builder bid requests to help builders identify clients and versions. Use `--builder-set-user-agent-header=false` to disable.
- Included more context when a request to an external signer fails.
- Added `/eth/v1/beacon/rewards/blocks/{block_id}` rest api endpoint.

### Bug Fixes
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"get" : {
"tags" : [ "Beacon", "Rewards" ],
"tags" : [ "Beacon", "Rewards", "Experimental" ],
"operationId" : "getBlockRewards",
"summary" : "Get Block Rewards",
"description" : "Retrieve block reward info for a single block.",
Expand Down Expand Up @@ -45,16 +45,6 @@
}
}
},
"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" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
},
"total" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"description" : "long string",
"example" : "1",
"format" : "uint64"
"format" : "long"
},
"attestations" : {
"type" : "string",
Expand All @@ -33,21 +33,21 @@
},
"sync_aggregate" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"description" : "long string",
"example" : "1",
"format" : "uint64"
"format" : "long"
},
"proposer_slashings" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"description" : "long string",
"example" : "1",
"format" : "uint64"
"format" : "long"
},
"attester_slashings" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"description" : "long string",
"example" : "1",
"format" : "uint64"
"format" : "long"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ private static RestApi create(
.endpoint(new GetVersion())
// Rewards Handlers
.endpoint(new GetSyncCommitteeRewards(dataProvider))
.endpoint(new GetBlockRewards())
.endpoint(new GetBlockRewards(dataProvider))
.endpoint(new GetAttestationRewards())
// Validator Handlers
.endpoint(new PostAttesterDuties(dataProvider))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,35 @@
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.EXECUTION_OPTIMISTIC;
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.http.RestApiConstants.TAG_EXPERIMENTAL;
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.TAG_REWARDS;
import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.BOOLEAN_TYPE;
import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.LONG_TYPE;
import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.UINT64_TYPE;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang3.NotImplementedException;
import tech.pegasys.teku.api.ChainDataProvider;
import tech.pegasys.teku.api.DataProvider;
import tech.pegasys.teku.api.migrated.BlockRewardData;
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.ObjectAndMetaData;

public class GetBlockRewards extends RestApiEndpoint {
public static final String ROUTE = "/eth/v1/beacon/rewards/blocks/{block_id}";
private final ChainDataProvider chainDataProvider;

private static final SerializableTypeDefinition<BlockRewardData> DATA_TYPE =
SerializableTypeDefinition.object(BlockRewardData.class)
.withField("proposer_index", UINT64_TYPE, BlockRewardData::getProposerIndex)
.withField("total", UINT64_TYPE, BlockRewardData::getTotal)
.withField("total", LONG_TYPE, BlockRewardData::getTotal)
.withField("attestations", LONG_TYPE, BlockRewardData::getAttestations)
.withField("sync_aggregate", UINT64_TYPE, BlockRewardData::getSyncAggregate)
.withField("proposer_slashings", UINT64_TYPE, BlockRewardData::getProposerSlashings)
.withField("attester_slashings", UINT64_TYPE, BlockRewardData::getAttesterSlashings)
.withField("sync_aggregate", LONG_TYPE, BlockRewardData::getSyncAggregate)
.withField("proposer_slashings", LONG_TYPE, BlockRewardData::getProposerSlashings)
.withField("attester_slashings", LONG_TYPE, BlockRewardData::getAttesterSlashings)
.build();

private static final SerializableTypeDefinition<ObjectAndMetaData<BlockRewardData>>
Expand All @@ -55,23 +59,34 @@ public class GetBlockRewards extends RestApiEndpoint {
.withField("data", DATA_TYPE, ObjectAndMetaData::getData)
.build();

public GetBlockRewards() {
public GetBlockRewards(final DataProvider dataProvider) {
this(dataProvider.getChainDataProvider());
}

public GetBlockRewards(final ChainDataProvider chainDataProvider) {
super(
EndpointMetadata.get(ROUTE)
.operationId("getBlockRewards")
.summary("Get Block Rewards")
.description("Retrieve block reward info for a single block.")
.tags(TAG_BEACON, TAG_REWARDS)
.tags(TAG_BEACON, TAG_REWARDS, TAG_EXPERIMENTAL)
.pathParam(PARAMETER_BLOCK_ID)
.response(SC_OK, "Request successful", RESPONSE_TYPE)
.withNotFoundResponse()
.withInternalErrorResponse()
.withNotImplementedResponse()
.build());
this.chainDataProvider = chainDataProvider;
}

@Override
public void handleRequest(RestApiRequest request) throws JsonProcessingException {
throw new NotImplementedException();
request.respondAsync(
chainDataProvider
.getBlockRewardsFromBlockId(request.getPathParameter(PARAMETER_BLOCK_ID))
.thenApply(
result ->
result
.map(AsyncApiResponse::respondOk)
.orElse(AsyncApiResponse.respondNotFound())));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,55 @@
package tech.pegasys.teku.beaconrestapi.handlers.v1.rewards;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_INTERNAL_SERVER_ERROR;
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.restapi.MetadataTestUtil.getResponseStringFromMetadata;
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.verifyMetadataErrorResponse;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.io.Resources;
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.AssertionsForClassTypes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.api.migrated.BlockRewardData;
import tech.pegasys.teku.beaconrestapi.AbstractMigratedBeaconHandlerTest;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.http.HttpStatusCodes;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.metadata.ObjectAndMetaData;

public class GetBlockRewardsTest extends AbstractMigratedBeaconHandlerTest {
private final BlockRewardData data =
new BlockRewardData(
UInt64.valueOf(123),
UInt64.valueOf(123),
123L,
UInt64.valueOf(123),
UInt64.valueOf(123),
UInt64.valueOf(123));
new BlockRewardData(UInt64.valueOf(123), 283L, 672L, 982L, 198L);
private final ObjectAndMetaData<BlockRewardData> blockRewardsResult =
new ObjectAndMetaData<>(data, SpecMilestone.ALTAIR, false, true, true);

@BeforeEach
void setUp() {
setHandler(new GetBlockRewards());
setHandler(new GetBlockRewards(chainDataProvider));
request.setPathParameter("block_id", "head");
}

@Test
void shouldReturnBlockAndRewardDataInformation()
throws JsonProcessingException, ExecutionException, InterruptedException {
when(chainDataProvider.getBlockRewardsFromBlockId(any()))
.thenReturn(SafeFuture.completedFuture(Optional.of(blockRewardsResult)));
handler.handleRequest(request);

final ObjectAndMetaData<BlockRewardData> output =
chainDataProvider.getBlockRewardsFromBlockId("head").get().orElseThrow();

Assertions.assertThat(request.getResponseCode()).isEqualTo(SC_OK);
assertThat(request.getResponseBody()).isEqualTo(output);
}

@Test
Expand All @@ -65,11 +80,6 @@ void metadata_shouldHandle500() throws JsonProcessingException {
verifyMetadataErrorResponse(handler, SC_INTERNAL_SERVER_ERROR);
}

@Test
void metadata_shouldHandle501() throws JsonProcessingException {
verifyMetadataErrorResponse(handler, SC_NOT_IMPLEMENTED);
}

@Test
void metadata_shouldHandle200() throws IOException {
final String data = getResponseStringFromMetadata(handler, SC_OK, blockRewardsResult);
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"execution_optimistic":false,"finalized":true,"data":{"proposer_index":"123","total":"123","attestations":"123","sync_aggregate":"123","proposer_slashings":"123","attester_slashings":"123"}}
{"execution_optimistic":false,"finalized":true,"data":{"proposer_index":"123","total":"2135","attestations":"283","sync_aggregate":"672","proposer_slashings":"982","attester_slashings":"198"}}
Loading

0 comments on commit 4d42661

Please sign in to comment.