Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mev Boost\Builder] validator registration beacon rest api (server side) #5545

Merged
merged 13 commits into from
May 24, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.bls.BLSSignature;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.ssz.SszList;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.networking.eth2.gossip.BlockGossipChannel;
import tech.pegasys.teku.networking.eth2.gossip.subnets.AttestationTopicSubscriber;
Expand All @@ -52,6 +53,7 @@
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState;
import tech.pegasys.teku.spec.datastructures.execution.SignedValidatorRegistration;
import tech.pegasys.teku.spec.datastructures.genesis.GenesisData;
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
import tech.pegasys.teku.spec.datastructures.operations.AttestationData;
Expand Down Expand Up @@ -623,6 +625,13 @@ public void prepareBeaconProposer(
beaconPreparableProposers, combinedChainDataClient.getCurrentSlot());
}

@Override
public SafeFuture<Void> registerValidators(
final SszList<SignedValidatorRegistration> validatorRegistrations) {
return proposersDataManager.updateValidatorRegistrations(
validatorRegistrations, combinedChainDataClient.getCurrentSlot());
}

private Optional<SubmitDataError> fromInternalValidationResult(
final InternalValidationResult internalValidationResult, final int resultIndex) {
if (!internalValidationResult.isReject()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2022 ConsenSys AG.
*
* 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.beaconrestapi.v1.validator;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_OK;
import static tech.pegasys.teku.spec.schemas.ApiSchemas.SIGNED_VALIDATOR_REGISTRATIONS_SCHEMA;

import java.io.IOException;
import okhttp3.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.beaconrestapi.AbstractDataBackedRestAPIIntegrationTest;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostRegisterValidator;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.json.JsonUtil;
import tech.pegasys.teku.infrastructure.ssz.SszList;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.execution.SignedValidatorRegistration;
import tech.pegasys.teku.spec.util.DataStructureUtil;

public class PostRegisterValidatorTest extends AbstractDataBackedRestAPIIntegrationTest {
private DataStructureUtil dataStructureUtil;

@BeforeEach
void setup() {
startRestAPIAtGenesis(SpecMilestone.BELLATRIX);
dataStructureUtil = new DataStructureUtil(spec);
}

@Test
void shouldReturnOk() throws IOException {
final SszList<SignedValidatorRegistration> request =
dataStructureUtil.randomValidatorRegistrations(10);

when(validatorApiChannel.registerValidators(request)).thenReturn(SafeFuture.COMPLETE);

Response response =
post(
PostRegisterValidator.ROUTE,
JsonUtil.serialize(
request, SIGNED_VALIDATOR_REGISTRATIONS_SCHEMA.getJsonTypeDefinition()));

assertThat(response.code()).isEqualTo(SC_OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"post" : {
"tags" : [ "Validator", "Validator Required Api" ],
"operationId" : "registerValidator",
"summary" : "Provide beacon node with registrations for the given validators to the external builder network.",
"description" : "Prepares the beacon node for engaging with external builders. The information will be sent by the beacon node to the builder network. It is expected that the validator client will send this information periodically to ensure the beacon node has correct and timely registration information to provide to builders. The validator client should not sign blinded beacon blocks that do not adhere to their latest fee recipient and gas limit preferences.",
"requestBody" : {
"content" : {
"application/octet-stream" : {
"schema" : {
"type" : "string",
"format" : "binary"
}
},
"application/json" : {
"schema" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/SignedValidatorRegistration"
}
}
}
}
},
"responses" : {
"200" : {
"description" : "Registration information has been received.",
"content" : { }
},
"400" : {
"description" : "The request could not be processed, check the response for more information.",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/HttpErrorResponse"
}
}
}
},
"500" : {
"description" : "Internal server error",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/HttpErrorResponse"
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"title" : "SignedValidatorRegistration",
"type" : "object",
"required" : [ "message", "signature" ],
"properties" : {
"message" : {
"$ref" : "#/components/schemas/ValidatorRegistration"
},
"signature" : {
"type" : "string",
"pattern" : "^0x[a-fA-F0-9]{2,}$",
"description" : "SSZ hexadecimal",
"format" : "bytes"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"title" : "ValidatorRegistration",
"type" : "object",
"required" : [ "fee_recipient", "gas_limit", "timestamp", "pubkey" ],
"properties" : {
"fee_recipient" : {
"type" : "string",
"pattern" : "^0x[a-fA-F0-9]{2,}$",
"description" : "SSZ hexadecimal",
"format" : "bytes"
},
"gas_limit" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"example" : "1",
"format" : "uint64"
},
"timestamp" : {
"type" : "string",
"description" : "unsigned 64 bit integer",
"example" : "1",
"format" : "uint64"
},
"pubkey" : {
"type" : "string",
"pattern" : "^0x[a-fA-F0-9]{2,}$",
"description" : "Bytes48 hexadecimal",
"format" : "bytes"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"post" : {
"tags" : [ "Validator", "Validator Required Api" ],
"summary" : "Provide beacon node with registrations for the given validators to the external builder network.",
"description" : "Prepares the beacon node for potential proposers by supplying information required when proposing blocks for the given validators. The information supplied for each validator index is considered persistent until overwritten by new information for the given validator index, or until the beacon node restarts.\n\nNote that because the information is not persistent across beacon node restarts it is recommended that either the beacon node is monitored for restarts or this information is refreshed by resending this request periodically (for example, each epoch).\n\nAlso note that requests containing currently inactive or unknown validator indices will be accepted, as they may become active at a later epoch.",
"operationId" : "postEthV1ValidatorRegister_validator",
"requestBody" : {
"content" : {
"application/json" : {
"schema" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/PostRegisterValidatorRequest"
}
}
}
}
},
"responses" : {
"200" : {
"description" : "Preparation information has been received."
},
"400" : {
"description" : "Invalid parameter supplied."
},
"500" : {
"description" : "Beacon node internal error."
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"fee_recipient" : {
"pattern" : "^0x[a-fA-F0-9]{40}$",
"type" : "string",
"description" : "Bytes20 hexadecimal",
"format" : "byte"
"description" : "An address on the execution (Ethereum 1) network.",
"example" : "0xabcf8e0d4e9587369b2301d0790347320302cc09"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"type" : "object",
"properties" : {
"message" : {
"$ref" : "#/components/schemas/ValidatorRegistration"
},
"signature" : {
"type" : "string",
"description" : "Bytes96 hexadecimal",
"format" : "byte"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"type" : "object",
"properties" : {
"fee_recipient" : {
"pattern" : "^0x[a-fA-F0-9]{40}$",
"type" : "string",
"description" : "An address on the execution (Ethereum 1) network.",
"example" : "0xabcf8e0d4e9587369b2301d0790347320302cc09"
},
"gas_limit" : {
"type" : "string",
"format" : "uint64",
"example" : "1"
},
"timestamp" : {
"type" : "string",
"format" : "uint64",
"example" : "1"
},
"pubkey" : {
"pattern" : "^0x[a-fA-F0-9]{96}$",
"type" : "string",
"description" : "The validator's BLS public key, uniquely identifying them. 48-bytes, hex encoded with 0x prefix, case insensitive.",
"example" : "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostAttesterDuties;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostContributionAndProofs;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostPrepareBeaconProposer;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostRegisterValidator;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostSubscribeToBeaconCommitteeSubnet;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostSyncCommitteeSubscriptions;
import tech.pegasys.teku.beaconrestapi.handlers.v1.validator.PostSyncDuties;
Expand Down Expand Up @@ -399,6 +400,7 @@ private void addValidatorHandlers(final DataProvider dataProvider, final Spec sp
app.post(
PostContributionAndProofs.ROUTE, new PostContributionAndProofs(dataProvider, jsonProvider));
addMigratedEndpoint(new PostPrepareBeaconProposer(dataProvider));
addMigratedEndpoint(new PostRegisterValidator(dataProvider));
}

private void addBeaconHandlers(final DataProvider dataProvider, final Spec spec) {
Expand Down
Loading