13
13
14
14
package tech .pegasys .teku .validator .remote .typedef ;
15
15
16
+ import static java .util .Collections .emptyMap ;
16
17
import static org .assertj .core .api .Assertions .assertThat ;
18
+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
17
19
import static org .assertj .core .api .Assumptions .assumeThat ;
20
+ import static tech .pegasys .teku .ethereum .json .types .beacon .StateValidatorDataBuilder .STATE_VALIDATORS_RESPONSE_TYPE ;
21
+ import static tech .pegasys .teku .infrastructure .http .HttpStatusCodes .SC_BAD_REQUEST ;
22
+ import static tech .pegasys .teku .infrastructure .http .HttpStatusCodes .SC_METHOD_NOT_ALLOWED ;
23
+ import static tech .pegasys .teku .infrastructure .http .HttpStatusCodes .SC_NOT_FOUND ;
24
+ import static tech .pegasys .teku .infrastructure .http .HttpStatusCodes .SC_NO_CONTENT ;
25
+ import static tech .pegasys .teku .infrastructure .http .HttpStatusCodes .SC_OK ;
26
+ import static tech .pegasys .teku .infrastructure .json .JsonUtil .serialize ;
27
+ import static tech .pegasys .teku .spec .config .SpecConfig .FAR_FUTURE_EPOCH ;
18
28
19
29
import com .fasterxml .jackson .core .JsonProcessingException ;
20
30
import com .fasterxml .jackson .databind .ObjectMapper ;
31
+ import java .util .List ;
21
32
import java .util .Optional ;
22
33
import okhttp3 .mockwebserver .MockResponse ;
23
34
import okhttp3 .mockwebserver .RecordedRequest ;
26
37
import org .junit .jupiter .api .BeforeEach ;
27
38
import org .junit .jupiter .api .TestTemplate ;
28
39
import tech .pegasys .teku .api .exceptions .RemoteServiceNotAvailableException ;
29
- import tech .pegasys .teku .infrastructure .json .JsonUtil ;
40
+ import tech .pegasys .teku .api .response .v1 .beacon .ValidatorStatus ;
41
+ import tech .pegasys .teku .ethereum .json .types .beacon .StateValidatorData ;
30
42
import tech .pegasys .teku .infrastructure .ssz .SszDataAssert ;
31
43
import tech .pegasys .teku .infrastructure .ssz .SszList ;
32
44
import tech .pegasys .teku .infrastructure .unsigned .UInt64 ;
37
49
import tech .pegasys .teku .spec .datastructures .blocks .SignedBeaconBlock ;
38
50
import tech .pegasys .teku .spec .datastructures .builder .SignedValidatorRegistration ;
39
51
import tech .pegasys .teku .spec .datastructures .metadata .BlockContainerAndMetaData ;
52
+ import tech .pegasys .teku .spec .datastructures .metadata .ObjectAndMetaData ;
53
+ import tech .pegasys .teku .spec .datastructures .state .Validator ;
40
54
import tech .pegasys .teku .spec .networks .Eth2Network ;
41
55
import tech .pegasys .teku .spec .schemas .ApiSchemas ;
42
56
import tech .pegasys .teku .validator .api .SendSignedBlockResult ;
43
57
import tech .pegasys .teku .validator .api .required .SyncingStatus ;
58
+ import tech .pegasys .teku .validator .remote .apiclient .PostStateValidatorsNotExistingException ;
59
+ import tech .pegasys .teku .validator .remote .apiclient .ValidatorApiMethod ;
44
60
import tech .pegasys .teku .validator .remote .typedef .handlers .RegisterValidatorsRequest ;
45
61
46
62
@ TestSpecContext (allMilestones = true , network = Eth2Network .MINIMAL )
@@ -136,7 +152,7 @@ void publishesBlindedBlockJsonEncoded() throws InterruptedException, JsonProcess
136
152
final RecordedRequest recordedRequest = mockWebServer .takeRequest ();
137
153
138
154
final String expectedRequest =
139
- JsonUtil . serialize (
155
+ serialize (
140
156
signedBeaconBlock ,
141
157
spec .atSlot (UInt64 .ONE )
142
158
.getSchemaDefinitions ()
@@ -193,7 +209,7 @@ void registerValidators_makesJsonRequest() throws InterruptedException, JsonProc
193
209
dataStructureUtil .randomSignedValidatorRegistrations (5 );
194
210
195
211
final String expectedRequest =
196
- JsonUtil . serialize (
212
+ serialize (
197
213
validatorRegistrations ,
198
214
ApiSchemas .SIGNED_VALIDATOR_REGISTRATIONS_SCHEMA .getJsonTypeDefinition ());
199
215
@@ -323,6 +339,77 @@ void blockV3ShouldFallbacksToBlockV2WhenNotFound()
323
339
assertThat (secondRequest .getPath ()).startsWith ("/eth/v1/validator/blinded_blocks" );
324
340
}
325
341
342
+ @ TestTemplate
343
+ void postValidators_MakesExpectedRequest () throws Exception {
344
+ mockWebServer .enqueue (new MockResponse ().setResponseCode (SC_NO_CONTENT ));
345
+
346
+ okHttpValidatorTypeDefClient .postStateValidators (List .of ("1" , "0x1234" ));
347
+
348
+ final RecordedRequest request = mockWebServer .takeRequest ();
349
+ assertThat (request .getMethod ()).isEqualTo ("POST" );
350
+
351
+ assertThat (request .getPath ()).contains (ValidatorApiMethod .GET_VALIDATORS .getPath (emptyMap ()));
352
+ assertThat (request .getBody ().readUtf8 ()).isEqualTo ("{\" ids\" :[\" 1\" ,\" 0x1234\" ]}" );
353
+ }
354
+
355
+ @ TestTemplate
356
+ public void postValidators_WhenNoContent_ReturnsEmpty () {
357
+ mockWebServer .enqueue (new MockResponse ().setResponseCode (SC_NO_CONTENT ));
358
+
359
+ assertThat (okHttpValidatorTypeDefClient .postStateValidators (List .of ("1" ))).isEmpty ();
360
+ }
361
+
362
+ @ TestTemplate
363
+ public void postValidators_WhenNotExisting_ThrowsException () {
364
+ final List <Integer > responseCodes =
365
+ List .of (SC_BAD_REQUEST , SC_NOT_FOUND , SC_METHOD_NOT_ALLOWED );
366
+ for (int code : responseCodes ) {
367
+ checkThrowsExceptionForCode (code );
368
+ }
369
+ }
370
+
371
+ private void checkThrowsExceptionForCode (final int responseCode ) {
372
+ mockWebServer .enqueue (new MockResponse ().setResponseCode (responseCode ));
373
+ assertThatThrownBy (() -> okHttpValidatorTypeDefClient .postStateValidators (List .of ("1" )))
374
+ .isInstanceOf (PostStateValidatorsNotExistingException .class );
375
+ }
376
+
377
+ @ TestTemplate
378
+ public void postValidators_WhenSuccess_ReturnsResponse () throws JsonProcessingException {
379
+ final List <StateValidatorData > expected =
380
+ List .of (generateStateValidatorData (), generateStateValidatorData ());
381
+ final ObjectAndMetaData <List <StateValidatorData >> response =
382
+ new ObjectAndMetaData <>(expected , specMilestone , false , true , false );
383
+
384
+ final String body = serialize (response , STATE_VALIDATORS_RESPONSE_TYPE );
385
+ mockWebServer .enqueue (new MockResponse ().setResponseCode (SC_OK ).setBody (body ));
386
+
387
+ Optional <List <StateValidatorData >> result =
388
+ okHttpValidatorTypeDefClient .postStateValidators (List .of ("1" , "2" ));
389
+
390
+ assertThat (result ).isPresent ();
391
+ assertThat (result .get ()).isEqualTo (expected );
392
+ }
393
+
394
+ private StateValidatorData generateStateValidatorData () {
395
+ final long index = dataStructureUtil .randomLong ();
396
+ final Validator validator =
397
+ new Validator (
398
+ dataStructureUtil .randomPublicKey (),
399
+ dataStructureUtil .randomBytes32 (),
400
+ dataStructureUtil .randomUInt64 (),
401
+ false ,
402
+ UInt64 .ZERO ,
403
+ UInt64 .ZERO ,
404
+ FAR_FUTURE_EPOCH ,
405
+ FAR_FUTURE_EPOCH );
406
+ return new StateValidatorData (
407
+ UInt64 .valueOf (index ),
408
+ dataStructureUtil .randomUInt64 (),
409
+ ValidatorStatus .active_ongoing ,
410
+ validator );
411
+ }
412
+
326
413
private void verifyRegisterValidatorsPostRequest (
327
414
final RecordedRequest recordedRequest , final String expectedContentType ) {
328
415
assertThat (recordedRequest .getPath ()).isEqualTo ("/eth/v1/validator/register_validator" );
@@ -341,7 +428,7 @@ private void assertJsonEquals(final String actual, final String expected) {
341
428
342
429
private String serializeBlockContainer (final BlockContainer blockContainer )
343
430
throws JsonProcessingException {
344
- return JsonUtil . serialize (
431
+ return serialize (
345
432
blockContainer ,
346
433
blockContainer .isBlinded ()
347
434
? schemaDefinitions .getBlindedBlockContainerSchema ().getJsonTypeDefinition ()
0 commit comments