Skip to content

Commit

Permalink
Handle SendTransaction separately from passthrough (Consensys#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
rain-on authored Apr 10, 2019
1 parent e83a81c commit 4dcf577
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 41 deletions.
14 changes: 4 additions & 10 deletions ethfirewall/src/main/java/tech/pegasys/ethfirewall/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import tech.pegasys.ethfirewall.jsonrpcproxy.EthAccountsBodyProvider;
import tech.pegasys.ethfirewall.jsonrpcproxy.HttpResponseFactory;
import tech.pegasys.ethfirewall.jsonrpcproxy.InternalResponseHandler;
import tech.pegasys.ethfirewall.jsonrpcproxy.JsonRpcBody;
import tech.pegasys.ethfirewall.jsonrpcproxy.JsonRpcErrorReporter;
import tech.pegasys.ethfirewall.jsonrpcproxy.JsonRpcHttpService;
import tech.pegasys.ethfirewall.jsonrpcproxy.PassThroughHandler;
import tech.pegasys.ethfirewall.jsonrpcproxy.RequestMapper;
import tech.pegasys.ethfirewall.jsonrpcproxy.SendTransactionBodyProvider;
import tech.pegasys.ethfirewall.jsonrpcproxy.SendTransactionHandler;
import tech.pegasys.ethfirewall.signing.TransactionSigner;

import java.time.Duration;
Expand All @@ -30,7 +30,6 @@
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.json.Json;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -76,17 +75,12 @@ private RequestMapper createRequestMapper(

final HttpClient downStreamConnection = vertx.createHttpClient(clientOptions);

final PassThroughHandler passThroughHandler =
new PassThroughHandler(
errorReporter,
downStreamConnection,
(jsonRpcRequest) -> new JsonRpcBody(Json.encodeToBuffer(jsonRpcRequest)));

final RequestMapper requestMapper = new RequestMapper(passThroughHandler);
final RequestMapper requestMapper =
new RequestMapper(new PassThroughHandler(downStreamConnection));

requestMapper.addHandler(
"eth_sendTransaction",
new PassThroughHandler(
new SendTransactionHandler(
errorReporter,
downStreamConnection,
new SendTransactionBodyProvider(transactionSigner)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,10 @@
public class PassThroughHandler implements JsonRpcRequestHandler {

private static final Logger LOG = LoggerFactory.getLogger(PassThroughHandler.class);
private final JsonRpcErrorReporter errorReporter;
private final HttpClient ethNodeClient;
private final BodyProvider bodyProvider;

public PassThroughHandler(
final JsonRpcErrorReporter errorReporter,
final HttpClient ethNodeClient,
final BodyProvider bodyProvider) {
this.errorReporter = errorReporter;
public PassThroughHandler(final HttpClient ethNodeClient) {
this.ethNodeClient = ethNodeClient;
this.bodyProvider = bodyProvider;
}

@Override
Expand All @@ -62,19 +55,10 @@ public void handle(final HttpServerRequest httpServerRequest, final JsonRpcReque
});

proxyRequest.headers().setAll(httpServerRequest.headers());
proxyRequest.headers().remove("Content-Length"); // created during 'end'.
proxyRequest.setChunked(false);

final JsonRpcBody providedBody = bodyProvider.getBody(request);

if (providedBody.hasError()) {
errorReporter.send(request, httpServerRequest, providedBody.error());
} else {
// Data is only written to the wire on end()
final Buffer proxyRequestBody = providedBody.body();
proxyRequest.end(proxyRequestBody);
logRequest(request, httpServerRequest, proxyRequest, proxyRequestBody);
}
proxyRequest.end(Json.encodeToBuffer(request));
logRequest(request, httpServerRequest);
}

private void logResponse(final HttpClientResponse response) {
Expand All @@ -85,18 +69,11 @@ private void logResponseBody(final Buffer body) {
LOG.debug("Response body: {}", body);
}

private void logRequest(
final JsonRpcRequest originalJsonRpcRequest,
final HttpServerRequest originalRequest,
final HttpClientRequest proxyRequest,
final Buffer proxyRequestBody) {
private void logRequest(final JsonRpcRequest jsonRequest, final HttpServerRequest httpRequest) {
LOG.debug(
"Original method: {}, uri: {}, body: {}, Proxy: method: {}, uri: {}, body: {}",
originalRequest.method(),
originalRequest.absoluteURI(),
Json.encodePrettily(originalJsonRpcRequest),
proxyRequest.method(),
proxyRequest.absoluteURI(),
proxyRequestBody);
"Proxying method: {}, uri: {}, body: {}",
httpRequest.method(),
httpRequest.absoluteURI(),
Json.encodePrettily(jsonRequest));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2019 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.ethfirewall.jsonrpcproxy;

import tech.pegasys.ethfirewall.jsonrpc.JsonRpcRequest;

import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.Json;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SendTransactionHandler implements JsonRpcRequestHandler {

private static final Logger LOG = LoggerFactory.getLogger(SendTransactionHandler.class);
private final JsonRpcErrorReporter errorReporter;
private final HttpClient ethNodeClient;
private final BodyProvider bodyProvider;

public SendTransactionHandler(
final JsonRpcErrorReporter errorReporter,
final HttpClient ethNodeClient,
final BodyProvider bodyProvider) {
this.errorReporter = errorReporter;
this.ethNodeClient = ethNodeClient;
this.bodyProvider = bodyProvider;
}

@Override
public void handle(final HttpServerRequest httpServerRequest, final JsonRpcRequest requestBody) {
final HttpClientRequest request =
ethNodeClient.request(
httpServerRequest.method(),
httpServerRequest.uri(),
proxiedResponse -> {
logResponse(proxiedResponse);

httpServerRequest.response().setStatusCode(proxiedResponse.statusCode());
httpServerRequest.response().headers().setAll(proxiedResponse.headers());
httpServerRequest.response().setChunked(false);

proxiedResponse.bodyHandler(
data -> {
logResponseBody(data);

// End the sendRequest, preventing any other handler from executing
httpServerRequest.response().end(data);
});
});

request.headers().setAll(httpServerRequest.headers());
request.headers().remove("Content-Length"); // created during 'end'.
request.setChunked(false);

final JsonRpcBody providedBody = bodyProvider.getBody(requestBody);

if (providedBody.hasError()) {
errorReporter.send(requestBody, httpServerRequest, providedBody.error());
} else {
// Data is only written to the wire on end()
final Buffer proxyRequestBody = providedBody.body();
request.end(proxyRequestBody);
logRequest(requestBody, httpServerRequest, request, proxyRequestBody);
}
}

private void logResponse(final HttpClientResponse response) {
LOG.debug("Response status: {}", response.statusCode());
}

private void logResponseBody(final Buffer body) {
LOG.debug("Response body: {}", body);
}

private void logRequest(
final JsonRpcRequest originalJsonRpcRequest,
final HttpServerRequest originalRequest,
final HttpClientRequest proxyRequest,
final Buffer proxyRequestBody) {
LOG.debug(
"Original method: {}, uri: {}, body: {}, Proxy: method: {}, uri: {}, body: {}",
originalRequest.method(),
originalRequest.absoluteURI(),
Json.encodePrettily(originalJsonRpcRequest),
proxyRequest.method(),
proxyRequest.absoluteURI(),
proxyRequestBody);
}
}

0 comments on commit 4dcf577

Please sign in to comment.