diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContract.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContract.java index 5c52556902..0f994139fd 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContract.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContract.java @@ -72,7 +72,7 @@ public BytesValue compute(final BytesValue input) { try { final Optional recovered = PublicKey.recoverFromSignature(h, signature); if (!recovered.isPresent()) { - return Bytes32.ZERO; + return Bytes32.EMPTY; } final Bytes32 hashed = Hash.hash(recovered.get().getEncodedBytes()); @@ -80,7 +80,7 @@ public BytesValue compute(final BytesValue input) { hashed.slice(12).copyTo(result, 12); return result; } catch (final IllegalArgumentException e) { - return Bytes32.ZERO; + return Bytes32.EMPTY; } } } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContractTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContractTest.java index f6bf7b6587..727b34d7e6 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContractTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/ECRECPrecompiledContractTest.java @@ -37,7 +37,7 @@ public static Object[][] parameters() { return new Object[][] { { "acb1c19ac0832320815b5e886c6b73ad7d6177853d44b026f2a7a9e11bb899fc000000000000000000000000000000000000000000000000000000000000001c89ea49159b334f9aebbf54481b69d000d285baa341899db355a4030f6838394e540e9f9fa17bef441e32d98d5f4554cfefdc6a56101352e4b92efafd0d9646e8", - "0x" + null }, { "0x0049872459827432342344987245982743234234498724598274323423429943000000000000000000000000000000000000000000000000000000000000001be8359c341771db7f9ea3a662a1741d27775ce277961470028e054ed3285aab8e31f63eaac35c4e6178abbc2a1073040ac9bbb0b67f2bc89a2e9593ba9abe8c53", @@ -454,7 +454,8 @@ public static Object[][] parameters() { @Test public void shouldRecoverAddress() { final BytesValue input = BytesValue.fromHexString(this.input); - final BytesValue expected = Bytes32.fromHexString(expectedResult); + final BytesValue expected = + expectedResult == null ? BytesValue.EMPTY : Bytes32.fromHexString(expectedResult); assertThat(contract.compute(input)).isEqualTo(expected); } } diff --git a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketService.java b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketService.java index 24e58b5795..9129d8f17c 100644 --- a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketService.java +++ b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketService.java @@ -22,6 +22,7 @@ import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; +import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.ServerWebSocket; import io.vertx.core.net.SocketAddress; import org.apache.logging.log4j.LogManager; @@ -62,6 +63,7 @@ public CompletableFuture start() { .setPort(configuration.getPort()) .setWebsocketSubProtocols("undefined")) .websocketHandler(websocketHandler()) + .requestHandler(httpHandler()) .listen(startHandler(resultFuture)); return resultFuture; @@ -103,6 +105,11 @@ private Handler websocketHandler() { }; } + private Handler httpHandler() { + return http -> + http.response().setStatusCode(400).end("Websocket endpoint can't handle HTTP requests"); + } + private Handler> startHandler(final CompletableFuture resultFuture) { return res -> { if (res.succeeded()) { diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketServiceTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketServiceTest.java index abd92a8bd1..131d025d08 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketServiceTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/websocket/WebSocketServiceTest.java @@ -25,6 +25,8 @@ import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpClientOptions; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.http.WebSocketBase; import io.vertx.ext.unit.Async; @@ -44,6 +46,7 @@ public class WebSocketServiceTest { private WebSocketConfiguration websocketConfiguration; private WebSocketRequestHandler webSocketRequestHandlerSpy; private WebSocketService websocketService; + private HttpClient httpClient; @Before public void before() { @@ -61,6 +64,13 @@ public void before() { websocketService.start().join(); websocketConfiguration.setPort(websocketService.socketAddress().getPort()); + + HttpClientOptions httpClientOptions = + new HttpClientOptions() + .setDefaultHost(websocketConfiguration.getHost()) + .setDefaultPort(websocketConfiguration.getPort()); + + httpClient = vertx.createHttpClient(httpClientOptions); } @After @@ -76,21 +86,17 @@ public void websocketServiceExecutesHandlerOnMessage(final TestContext context) final String request = "{\"id\": 1, \"method\": \"eth_subscribe\", \"params\": [\"syncing\"]}"; final String expectedResponse = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"0x1\"}"; - vertx - .createHttpClient() - .websocket( - websocketConfiguration.getPort(), - websocketConfiguration.getHost(), - "/", - webSocket -> { - webSocket.write(Buffer.buffer(request)); + httpClient.websocket( + "/", + webSocket -> { + webSocket.write(Buffer.buffer(request)); - webSocket.handler( - buffer -> { - context.assertEquals(expectedResponse, buffer.toString()); - async.complete(); - }); - }); + webSocket.handler( + buffer -> { + context.assertEquals(expectedResponse, buffer.toString()); + async.complete(); + }); + }); async.awaitSuccess(VERTX_AWAIT_TIMEOUT_MILLIS); } @@ -107,15 +113,7 @@ public void websocketServiceRemoveSubscriptionOnConnectionClose(final TestContex context.assertNotNull(m.body()); async.complete(); }) - .completionHandler( - v -> - vertx - .createHttpClient() - .websocket( - websocketConfiguration.getPort(), - websocketConfiguration.getHost(), - "/", - WebSocketBase::close)); + .completionHandler(v -> httpClient.websocket("/", WebSocketBase::close)); async.awaitSuccess(VERTX_AWAIT_TIMEOUT_MILLIS); } @@ -127,16 +125,35 @@ public void websocketServiceCloseConnectionOnUnrecoverableError(final TestContex final byte[] bigMessage = new byte[HttpServerOptions.DEFAULT_MAX_WEBSOCKET_MESSAGE_SIZE + 1]; Arrays.fill(bigMessage, (byte) 1); - vertx - .createHttpClient() - .websocket( + httpClient.websocket( + "/", + webSocket -> { + webSocket.write(Buffer.buffer(bigMessage)); + webSocket.closeHandler(v -> async.complete()); + }); + + async.awaitSuccess(VERTX_AWAIT_TIMEOUT_MILLIS); + } + + @Test + public void websocketServiceMustReturnErrorOnHttpRequest(final TestContext context) { + final Async async = context.async(); + + httpClient + .post( websocketConfiguration.getPort(), websocketConfiguration.getHost(), "/", - webSocket -> { - webSocket.write(Buffer.buffer(bigMessage)); - webSocket.closeHandler(v -> async.complete()); - }); + response -> + response.bodyHandler( + b -> { + context + .assertEquals(400, response.statusCode()) + .assertEquals( + "Websocket endpoint can't handle HTTP requests", b.toString()); + async.complete(); + })) + .end(); async.awaitSuccess(VERTX_AWAIT_TIMEOUT_MILLIS); } diff --git a/quickstart/listQuickstartServices.sh b/quickstart/listQuickstartServices.sh index 64019b1cd7..2482aba558 100755 --- a/quickstart/listQuickstartServices.sh +++ b/quickstart/listQuickstartServices.sh @@ -57,7 +57,7 @@ if [ ${#dots} -gt ${maxRetryCount} ]; then echo "****************************************************************${NORMAL}" else echo "JSON-RPC ${BOLD}HTTP${NORMAL}${CYAN} service endpoint : ${ORANGE}http://${HOST}:${explorerMapping##*:}/jsonrpc${CYAN} *" - echo "JSON-RPC ${BOLD}WebSocket${NORMAL}${CYAN} service endpoint : ${ORANGE}http://${HOST}:${explorerMapping##*:}/jsonws${CYAN} *" + echo "JSON-RPC ${BOLD}WebSocket${NORMAL}${CYAN} service endpoint : ${ORANGE}ws://${HOST}:${explorerMapping##*:}/jsonws${CYAN} *" echo "${CYAN}Web block explorer address : ${ORANGE}http://${HOST}:${explorerMapping##*:}${CYAN} * " echo "****************************************************************${NORMAL}" fi diff --git a/quickstart/src/test/java/tech/pegasys/pantheon/tests/quickstart/DockerQuickstartTest.java b/quickstart/src/test/java/tech/pegasys/pantheon/tests/quickstart/DockerQuickstartTest.java index 924738920e..5ea600f3d2 100644 --- a/quickstart/src/test/java/tech/pegasys/pantheon/tests/quickstart/DockerQuickstartTest.java +++ b/quickstart/src/test/java/tech/pegasys/pantheon/tests/quickstart/DockerQuickstartTest.java @@ -293,7 +293,8 @@ private enum EndpointsIdentifier { final Pattern pattern; EndpointsIdentifier(final String lineLabel) { - pattern = Pattern.compile(lineLabel + ".+(http://.+:[0-9]+)", Pattern.DOTALL); + pattern = + Pattern.compile(lineLabel + ".+((http|ws)://.+:[0-9]+/{0,1}[a-z]*)", Pattern.DOTALL); } }