Skip to content

Commit 6cfc626

Browse files
committed
Merge branch 'set-graffiti' into graffiti-management
2 parents 4656de9 + 5750b5f commit 6cfc626

File tree

4 files changed

+207
-0
lines changed

4 files changed

+207
-0
lines changed

validator/client/src/main/java/tech/pegasys/teku/validator/client/restapi/ValidatorRestApi.java

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import tech.pegasys.teku.validator.client.restapi.apis.PostVoluntaryExit;
5151
import tech.pegasys.teku.validator.client.restapi.apis.SetFeeRecipient;
5252
import tech.pegasys.teku.validator.client.restapi.apis.SetGasLimit;
53+
import tech.pegasys.teku.validator.client.restapi.apis.SetGraffiti;
5354
import tech.pegasys.teku.validator.client.slashingriskactions.SlashingRiskAction;
5455

5556
public class ValidatorRestApi {
@@ -131,6 +132,7 @@ public static RestApi create(
131132
.endpoint(new DeleteGasLimit(proposerConfigManager))
132133
.endpoint(new PostVoluntaryExit(voluntaryExitDataProvider))
133134
.endpoint(new GetGraffiti())
135+
.endpoint(new SetGraffiti())
134136
.sslCertificate(config.getRestApiKeystoreFile(), config.getRestApiKeystorePasswordFile())
135137
.passwordFilePath(validatorApiBearerFile)
136138
.build();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2024
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.validator.client.restapi.apis;
15+
16+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NO_CONTENT;
17+
import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.STRING_TYPE;
18+
import static tech.pegasys.teku.validator.client.restapi.ValidatorRestApi.TAG_GRAFFITI;
19+
import static tech.pegasys.teku.validator.client.restapi.ValidatorTypes.PARAM_PUBKEY_TYPE;
20+
21+
import com.fasterxml.jackson.core.JsonProcessingException;
22+
import org.apache.commons.lang3.NotImplementedException;
23+
import tech.pegasys.teku.infrastructure.restapi.endpoints.EndpointMetadata;
24+
import tech.pegasys.teku.infrastructure.restapi.endpoints.RestApiEndpoint;
25+
import tech.pegasys.teku.infrastructure.restapi.endpoints.RestApiRequest;
26+
27+
public class SetGraffiti extends RestApiEndpoint {
28+
29+
public SetGraffiti() {
30+
super(
31+
EndpointMetadata.post(GetGraffiti.ROUTE)
32+
.operationId("setGraffiti")
33+
.summary("Set Graffiti")
34+
.description("Set the graffiti for an individual validator.")
35+
.tags(TAG_GRAFFITI)
36+
.withBearerAuthSecurity()
37+
.pathParam(PARAM_PUBKEY_TYPE)
38+
.requestBodyType(STRING_TYPE.withDescription("Graffiti string"))
39+
.response(SC_NO_CONTENT, "Successfully updated graffiti.")
40+
.withAuthenticationResponses()
41+
.withNotFoundResponse()
42+
.withNotImplementedResponse()
43+
.build());
44+
}
45+
46+
@Override
47+
public void handleRequest(final RestApiRequest request) throws JsonProcessingException {
48+
throw new NotImplementedException("Not Implemented");
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright Consensys Software Inc., 2024
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package tech.pegasys.teku.validator.client.restapi.apis;
15+
16+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_BAD_REQUEST;
17+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_FORBIDDEN;
18+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_INTERNAL_SERVER_ERROR;
19+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NOT_IMPLEMENTED;
20+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_NO_CONTENT;
21+
import static tech.pegasys.teku.infrastructure.http.HttpStatusCodes.SC_UNAUTHORIZED;
22+
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.verifyMetadataEmptyResponse;
23+
import static tech.pegasys.teku.infrastructure.restapi.MetadataTestUtil.verifyMetadataErrorResponse;
24+
25+
import com.fasterxml.jackson.core.JsonProcessingException;
26+
import org.junit.jupiter.api.Test;
27+
28+
class SetGraffitiTest {
29+
private final SetGraffiti handler = new SetGraffiti();
30+
31+
@Test
32+
void metadata_shouldHandle204() {
33+
verifyMetadataEmptyResponse(handler, SC_NO_CONTENT);
34+
}
35+
36+
@Test
37+
void metadata_shouldHandle400() throws JsonProcessingException {
38+
verifyMetadataErrorResponse(handler, SC_BAD_REQUEST);
39+
}
40+
41+
@Test
42+
void metadata_shouldHandle401() throws JsonProcessingException {
43+
verifyMetadataErrorResponse(handler, SC_UNAUTHORIZED);
44+
}
45+
46+
@Test
47+
void metadata_shouldHandle403() throws JsonProcessingException {
48+
verifyMetadataErrorResponse(handler, SC_FORBIDDEN);
49+
}
50+
51+
@Test
52+
void metadata_shouldHandle500() throws JsonProcessingException {
53+
verifyMetadataErrorResponse(handler, SC_INTERNAL_SERVER_ERROR);
54+
}
55+
56+
@Test
57+
void metadata_shouldHandle501() throws JsonProcessingException {
58+
verifyMetadataErrorResponse(handler, SC_NOT_IMPLEMENTED);
59+
}
60+
}

validator/client/src/test/resources/tech/pegasys/teku/validator/client/restapi/paths/_eth_v1_validator_{pubkey}_graffiti.json

+95
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,100 @@
8989
}
9090
}
9191
}
92+
},
93+
"post" : {
94+
"tags" : [ "Graffiti" ],
95+
"operationId" : "setGraffiti",
96+
"summary" : "Set Graffiti",
97+
"description" : "Set the graffiti for an individual validator.",
98+
"parameters" : [ {
99+
"name" : "pubkey",
100+
"required" : true,
101+
"in" : "path",
102+
"schema" : {
103+
"type" : "string",
104+
"pattern" : "^0x[a-fA-F0-9]{96}$",
105+
"example" : "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"
106+
}
107+
} ],
108+
"requestBody" : {
109+
"content" : {
110+
"application/json" : {
111+
"schema" : {
112+
"type" : "string",
113+
"description" : "Graffiti string"
114+
}
115+
}
116+
}
117+
},
118+
"security" : [ {
119+
"bearerAuth" : [ ]
120+
} ],
121+
"responses" : {
122+
"204" : {
123+
"description" : "Successfully updated graffiti.",
124+
"content" : { }
125+
},
126+
"401" : {
127+
"description" : "Unauthorized, no token is found",
128+
"content" : {
129+
"application/json" : {
130+
"schema" : {
131+
"$ref" : "#/components/schemas/HttpErrorResponse"
132+
}
133+
}
134+
}
135+
},
136+
"403" : {
137+
"description" : "Forbidden, a token is found but is invalid",
138+
"content" : {
139+
"application/json" : {
140+
"schema" : {
141+
"$ref" : "#/components/schemas/HttpErrorResponse"
142+
}
143+
}
144+
}
145+
},
146+
"404" : {
147+
"description" : "Not found",
148+
"content" : {
149+
"application/json" : {
150+
"schema" : {
151+
"$ref" : "#/components/schemas/HttpErrorResponse"
152+
}
153+
}
154+
}
155+
},
156+
"501" : {
157+
"description" : "Not implemented",
158+
"content" : {
159+
"application/json" : {
160+
"schema" : {
161+
"$ref" : "#/components/schemas/HttpErrorResponse"
162+
}
163+
}
164+
}
165+
},
166+
"400" : {
167+
"description" : "The request could not be processed, check the response for more information.",
168+
"content" : {
169+
"application/json" : {
170+
"schema" : {
171+
"$ref" : "#/components/schemas/HttpErrorResponse"
172+
}
173+
}
174+
}
175+
},
176+
"500" : {
177+
"description" : "Internal server error",
178+
"content" : {
179+
"application/json" : {
180+
"schema" : {
181+
"$ref" : "#/components/schemas/HttpErrorResponse"
182+
}
183+
}
184+
}
185+
}
186+
}
92187
}
93188
}

0 commit comments

Comments
 (0)