Skip to content

Commit

Permalink
refactor create aggregate attestation request (#8496)
Browse files Browse the repository at this point in the history
* refactor create aggregate attestation request

* refactor
  • Loading branch information
mehdi-aouadi authored Aug 2, 2024
1 parent f5150b1 commit 7455d50
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ private AttestationData createAttestationData(
}

@Override
public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
final UInt64 slot,
final Bytes32 attestationHashTreeRoot,
final Optional<UInt64> committeeIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ public void createAttestationData_shouldUseCorrectSourceWhenEpochTransitionRequi
@Test
public void createAggregate_shouldFailWhenNodeIsSyncing() {
nodeIsSyncing();
final SafeFuture<Optional<? extends Attestation>> result =
final SafeFuture<Optional<Attestation>> result =
validatorApiHandler.createAggregate(
ONE, dataStructureUtil.randomAttestationData().hashTreeRoot(), Optional.empty());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public void handleRequest(final RestApiRequest request) throws JsonProcessingExc
final Bytes32 beaconBlockRoot = request.getQueryParameter(ATTESTATION_DATA_ROOT_PARAMETER);
final UInt64 slot = request.getQueryParameter(SLOT_PARAM);

final SafeFuture<Optional<? extends Attestation>> future =
final SafeFuture<Optional<Attestation>> future =
provider.createAggregate(slot, beaconBlockRoot, Optional.empty());

request.respondAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ private Optional<SyncCommitteeMessage> checkInternalCommitteeSignature(
return Optional.of(message);
}

public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
final UInt64 slot,
final Bytes32 attestationHashTreeRoot,
final Optional<UInt64> committeeIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public SafeFuture<Optional<AttestationData>> createAttestationData(
}

@Override
public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
UInt64 slot, Bytes32 attestationHashTreeRoot, Optional<UInt64> committeeIndex) {
return SafeFuture.completedFuture(Optional.empty());
}
Expand Down Expand Up @@ -231,7 +231,7 @@ SafeFuture<Optional<BlockContainerAndMetaData>> createUnsignedBlock(

SafeFuture<Optional<AttestationData>> createAttestationData(UInt64 slot, int committeeIndex);

SafeFuture<Optional<? extends Attestation>> createAggregate(
SafeFuture<Optional<Attestation>> createAggregate(
UInt64 slot, Bytes32 attestationHashTreeRoot, Optional<UInt64> committeeIndex);

SafeFuture<Optional<SyncCommitteeContribution>> createSyncCommitteeContribution(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ public SafeFuture<Optional<AttestationData>> createAttestationData(
}

@Override
public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
final UInt64 slot,
final Bytes32 attestationHashTreeRoot,
final Optional<UInt64> committeeIndex) {
return countOptionalExtendedDataRequest(
return countOptionalDataRequest(
delegate.createAggregate(slot, attestationHashTreeRoot, committeeIndex),
BeaconNodeRequestLabels.CREATE_AGGREGATE_METHOD);
}
Expand Down Expand Up @@ -298,16 +298,6 @@ private <T> SafeFuture<Optional<T>> countOptionalDataRequest(
__ -> recordSuccess(requestName), () -> recordDataUnavailable(requestName)));
}

private <T> SafeFuture<Optional<? extends T>> countOptionalExtendedDataRequest(
final SafeFuture<Optional<? extends T>> request, final String requestName) {
return request
.catchAndRethrow(__ -> recordError(requestName))
.thenPeek(
result ->
result.ifPresentOrElse(
__ -> recordSuccess(requestName), () -> recordDataUnavailable(requestName)));
}

private <T> SafeFuture<List<T>> countSendRequest(
final SafeFuture<List<T>> request, final String requestName) {
return request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,10 @@ public static Stream<Arguments> getDataRequestArguments() {
dataStructureUtil.randomUInt64(),
dataStructureUtil.randomUInt64());
final UInt64 epoch = dataStructureUtil.randomEpoch();
final Function<ValidatorApiChannel, SafeFuture<Optional<? extends Attestation>>>
createAggregateMethod =
channel ->
channel.createAggregate(
attestationData.getSlot(), attestationData.hashTreeRoot(), Optional.empty());
final Function<ValidatorApiChannel, SafeFuture<Optional<Attestation>>> createAggregateMethod =
channel ->
channel.createAggregate(
attestationData.getSlot(), attestationData.hashTreeRoot(), Optional.empty());
return Stream.of(
requestDataTest(
"getGenesisData",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public SafeFuture<ProductionResult<SignedAggregateAndProof>> createAggregate(

final AttestationData attestationData = maybeAttestation.get();

final SafeFuture<Optional<? extends Attestation>> createAggregationFuture =
final SafeFuture<Optional<Attestation>> createAggregationFuture =
validatorDutyMetrics.record(
() ->
validatorApiChannel.createAggregate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ public void createAggregate_WhenSuccess_ReturnsAttestation() throws JsonProcessi
mockWebServer.enqueue(
new MockResponse().setResponseCode(SC_OK).setBody("{\"data\": " + body + "}"));

final Optional<? extends Attestation> attestation =
final Optional<Attestation> attestation =
okHttpValidatorTypeDefClient.createAggregate(UInt64.ONE, attestationHashTreeRoot);

assertThat(attestation).isPresent();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright Consensys Software Inc., 2024
*
* 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.validator.remote.typedef.handlers;

import static org.assertj.core.api.Assertions.assertThat;
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.RestApiConstants.ATTESTATION_DATA_ROOT;
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.SLOT;

import java.util.Collections;
import java.util.Optional;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.RecordedRequest;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestTemplate;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.TestSpecContext;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.networks.Eth2Network;
import tech.pegasys.teku.validator.remote.apiclient.ValidatorApiMethod;
import tech.pegasys.teku.validator.remote.typedef.AbstractTypeDefRequestTestBase;

@TestSpecContext(milestone = SpecMilestone.PHASE0, network = Eth2Network.MINIMAL)
public class CreateAggregateAttestationRequestTest extends AbstractTypeDefRequestTestBase {

private CreateAggregateAttestationRequest createAggregateAttestationRequest;
private final UInt64 slot = UInt64.ONE;

@BeforeEach
void setupRequest() {
createAggregateAttestationRequest =
new CreateAggregateAttestationRequest(mockWebServer.url("/"), okHttpClient, slot, spec);
}

@TestTemplate
public void getAggregateAttestation_makesExpectedRequest() throws Exception {
final Bytes32 attestationHashTreeRoot = dataStructureUtil.randomBytes32();

mockWebServer.enqueue(new MockResponse().setResponseCode(SC_NO_CONTENT));

createAggregateAttestationRequest.createAggregate(attestationHashTreeRoot);

final RecordedRequest request = mockWebServer.takeRequest();
assertThat(request.getMethod()).isEqualTo("GET");
assertThat(request.getPath())
.contains(ValidatorApiMethod.GET_AGGREGATE.getPath(Collections.emptyMap()));
assertThat(request.getRequestUrl().queryParameter(SLOT)).isEqualTo(slot.toString());
assertThat(request.getRequestUrl().queryParameter(ATTESTATION_DATA_ROOT))
.isEqualTo(attestationHashTreeRoot.toHexString());
}

@TestTemplate
public void shouldGetAggregateAttestation() {
final Attestation attestation = dataStructureUtil.randomAttestation();
final CreateAggregateAttestationRequest.GetAggregateAttestationResponse
getAggregateAttestationResponse =
new CreateAggregateAttestationRequest.GetAggregateAttestationResponse(attestation);
final String mockResponse =
readResource(
"responses/create_aggregate_attestation_responses/createAggregateAttestationResponse.json");

mockWebServer.enqueue(new MockResponse().setResponseCode(SC_OK).setBody(mockResponse));

final Optional<Attestation> maybeAttestation =
createAggregateAttestationRequest.createAggregate(attestation.hashTreeRoot());

assertThat(maybeAttestation).isPresent();
assertThat(maybeAttestation.get()).isEqualTo(getAggregateAttestationResponse.getData());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"data": {
"aggregation_bits": "0x4a9278690f62e1a353f1abf2b9701e13e8cdf4d9ac6b032ba43b05b25f713540ce24f3192819e752fb091217ff34b68e934a06d316b6060696f8f24749574c4b3ac2e4ccb6914c434b09a81fff523e12acbe299fcdad715593298d72ca70e1ffc743ad7ce89587fbb4b4c57db7856b7082db70ebddcbebe264f886236df2dd51539e10d4dcd5950e6cea7c993d3e999a5589a4c71669ffb1390987e43a8c4790a70275364f96cbee34b0b5a9d1b3da4322ad12e07c81c6e6430d2528f19bb1727c3f63f414885bd97505283b0bb6773712096d5feb67c43d67f2fbf17bf796ed5080aece6b968d532d985ad2553daf31ad4022aa49d7a92ada719c9f93ab4b6f01",
"data": {
"slot": "4665021361504678828",
"index": "4669978815449698508",
"beacon_block_root": "0x103ac9406cdc59b89027eb1c9e97f607dd5fdccfa8fb2da4eaeea9d25032add9",
"source": {
"epoch": "542502839",
"root": "0x8200a6402ca295554fb9562193cc71d60272d63beeaf2201fdf53e846e77f919"
},
"target": {
"epoch": "542887588",
"root": "0x5cbeb140ec0ad7cb653388caecba483cf66bd817821ed18ca1f3b7f3b9b58a04"
}
},
"signature": "0xae401f767ab1917f925fe299ad51a57d52f7cc80deb1cc20fa2b3aa983e4e4d23056d79f01f3c97e29c8905da17e70e30c2a3f6bdd83dbc4ddf530e02e8f4d7ba22260e12e5f5fe7875b48e79660615b275597e87b2d33e076664b3da1737852"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public SafeFuture<Optional<AttestationData>> createAttestationData(
}

@Override
public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
final UInt64 slot,
final Bytes32 attestationHashTreeRoot,
final Optional<UInt64> committeeIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ private List<SubmitDataError> convertPostDataFailureResponseToSubmitDataErrors(
}

@Override
public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
final UInt64 slot,
final Bytes32 attestationHashTreeRoot,
final Optional<UInt64> committeeIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public SafeFuture<Optional<AttestationData>> createAttestationData(
}

@Override
public SafeFuture<Optional<? extends Attestation>> createAggregate(
public SafeFuture<Optional<Attestation>> createAggregate(
final UInt64 slot,
final Bytes32 attestationHashTreeRoot,
final Optional<UInt64> committeeIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ public class OkHttpValidatorTypeDefClient extends OkHttpValidatorMinimalTypeDefC
private final SendContributionAndProofsRequest sendContributionAndProofsRequest;
private final SubscribeToBeaconCommitteeRequest subscribeToBeaconCommitteeRequest;
private final PrepareBeaconProposersRequest prepareBeaconProposersRequest;
private final CreateAggregateAttestationRequest createAggregateAttestationRequest;

public OkHttpValidatorTypeDefClient(
final OkHttpClient okHttpClient,
Expand Down Expand Up @@ -131,8 +130,6 @@ public OkHttpValidatorTypeDefClient(
new SubscribeToBeaconCommitteeRequest(baseEndpoint, okHttpClient);
this.prepareBeaconProposersRequest =
new PrepareBeaconProposersRequest(baseEndpoint, okHttpClient);
this.createAggregateAttestationRequest =
new CreateAggregateAttestationRequest(baseEndpoint, okHttpClient, spec);
}

public SyncingStatus getSyncingStatus() {
Expand Down Expand Up @@ -264,8 +261,10 @@ public void prepareBeaconProposer(
prepareBeaconProposersRequest.submit(beaconPreparableProposers);
}

public Optional<? extends Attestation> createAggregate(
public Optional<Attestation> createAggregate(
final UInt64 slot, final Bytes32 attestationHashTreeRoot) {
return createAggregateAttestationRequest.createAggregate(slot, attestationHashTreeRoot);
final CreateAggregateAttestationRequest createAggregateAttestationRequest =
new CreateAggregateAttestationRequest(getBaseEndpoint(), getOkHttpClient(), slot, spec);
return createAggregateAttestationRequest.createAggregate(attestationHashTreeRoot);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,78 @@

package tech.pegasys.teku.validator.remote.typedef.handlers;

import static tech.pegasys.teku.ethereum.json.types.SharedApiTypes.withDataWrapper;
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.ATTESTATION_DATA_ROOT;
import static tech.pegasys.teku.infrastructure.http.RestApiConstants.SLOT;
import static tech.pegasys.teku.validator.remote.apiclient.ValidatorApiMethod.GET_AGGREGATE;

import java.util.Map;
import java.util.Optional;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.infrastructure.json.types.DeserializableTypeDefinition;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.datastructures.operations.AttestationSchema;
import tech.pegasys.teku.validator.remote.typedef.ResponseHandler;

public class CreateAggregateAttestationRequest extends AbstractTypeDefRequest {
private final Spec spec;
private final UInt64 slot;
final AttestationSchema<Attestation> attestationSchema;
private final ResponseHandler<GetAggregateAttestationResponse> responseHandler;

private final DeserializableTypeDefinition<GetAggregateAttestationResponse>
getAggregateAttestationTypeDef;

public CreateAggregateAttestationRequest(
final HttpUrl baseEndpoint, final OkHttpClient okHttpClient, final Spec spec) {
final HttpUrl baseEndpoint,
final OkHttpClient okHttpClient,
final UInt64 slot,
final Spec spec) {
super(baseEndpoint, okHttpClient);
this.spec = spec;
this.slot = slot;
this.attestationSchema =
spec.atSlot(slot)
.getSchemaDefinitions()
.getAttestationSchema()
.castTypeToAttestationSchema();
this.getAggregateAttestationTypeDef =
DeserializableTypeDefinition.object(GetAggregateAttestationResponse.class)
.initializer(GetAggregateAttestationResponse::new)
.withField(
"data",
attestationSchema.getJsonTypeDefinition(),
GetAggregateAttestationResponse::getData,
GetAggregateAttestationResponse::setData)
.build();

this.responseHandler = new ResponseHandler<>(getAggregateAttestationTypeDef);
}

public Optional<? extends Attestation> createAggregate(
final UInt64 slot, final Bytes32 attestationHashTreeRoot) {
public Optional<Attestation> createAggregate(final Bytes32 attestationHashTreeRoot) {
final Map<String, String> queryParams =
Map.of(
"slot", slot.toString(), "attestation_data_root", attestationHashTreeRoot.toString());
final AttestationSchema<? extends Attestation> attestationSchema =
spec.atSlot(slot).getSchemaDefinitions().getAttestationSchema();
Map.of(SLOT, slot.toString(), ATTESTATION_DATA_ROOT, attestationHashTreeRoot.toString());
return get(GET_AGGREGATE, queryParams, responseHandler)
.map(GetAggregateAttestationResponse::getData);
}

public static class GetAggregateAttestationResponse {

private Attestation data;

public GetAggregateAttestationResponse() {}

public GetAggregateAttestationResponse(final Attestation data) {
this.data = data;
}

public Attestation getData() {
return data;
}

return get(
GET_AGGREGATE, queryParams, new ResponseHandler<>(withDataWrapper(attestationSchema)));
public void setData(final Attestation data) {
this.data = data;
}
}
}
Loading

0 comments on commit 7455d50

Please sign in to comment.