Skip to content

Commit

Permalink
Rework how filter and log query parameters are created/used (#146)
Browse files Browse the repository at this point in the history
* Rework how filter and log query parameters are created/used

We used a `FilterParameter` that held strings in places where we could
create strongly typed objects. We also used it in places where we only
wanted a subset of its descriptiveness, namely, the `LogsQuery` part of
it.

* deserialize directly into `LogsQuery`, which is useful for log pub/sub
* narrow uses of `FilterParameter` to `LogsQuery` where possible
* make `FilterParameter` hold strongly typed `Address`s and `LogTopic`s

Signed-off-by: Ratan Rai Sur <ratan.r.sur@gmail.com>
  • Loading branch information
RatanRSur authored Oct 30, 2019
1 parent a07b450 commit a48a2de
Show file tree
Hide file tree
Showing 16 changed files with 179 additions and 312 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ public JsonRpcResponse response(final JsonRpcRequest request) {
final FilterParameter filter =
parameters.required(request.getParams(), 0, FilterParameter.class);
final LogsQuery query =
new LogsQuery.Builder()
.addresses(filter.getAddresses())
.topics(filter.getTopics().getTopics())
.build();
new LogsQuery.Builder().addresses(filter.getAddresses()).topics(filter.getTopics()).build();

if (isValid(filter)) {
return new JsonRpcErrorResponse(request.getId(), JsonRpcError.INVALID_PARAMS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters;

import org.hyperledger.besu.ethereum.api.query.TopicsParameter;
import static java.util.Collections.emptyList;

import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.LogTopic;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonCreator;
Expand All @@ -33,34 +33,26 @@ public class FilterParameter {
private final BlockParameter fromBlock;
private final BlockParameter toBlock;
private final List<Address> addresses;
private final TopicsParameter topics;
private final List<List<LogTopic>> topics;
private final Hash blockhash;

@JsonCreator
public FilterParameter(
@JsonProperty("fromBlock") final String fromBlock,
@JsonProperty("toBlock") final String toBlock,
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) @JsonProperty("address")
final List<String> address,
final List<Address> address,
@JsonDeserialize(using = TopicsDeserializer.class) @JsonProperty("topics")
final TopicsParameter topics,
final List<List<LogTopic>> topics,
@JsonProperty("blockhash") final String blockhash) {
this.fromBlock =
fromBlock != null ? new BlockParameter(fromBlock) : new BlockParameter("latest");
this.toBlock = toBlock != null ? new BlockParameter(toBlock) : new BlockParameter("latest");
this.addresses = address != null ? renderAddress(address) : Collections.emptyList();
this.topics = topics != null ? topics : new TopicsParameter(Collections.emptyList());
this.addresses = address != null ? address : emptyList();
this.topics = topics != null ? topics : emptyList();
this.blockhash = blockhash != null ? Hash.fromHexString(blockhash) : null;
}

private List<Address> renderAddress(final List<String> inputAddresses) {
final List<Address> addresses = new ArrayList<>();
for (final String value : inputAddresses) {
addresses.add(Address.fromHexString(value));
}
return addresses;
}

public BlockParameter getFromBlock() {
return fromBlock;
}
Expand All @@ -73,7 +65,7 @@ public List<Address> getAddresses() {
return addresses;
}

public TopicsParameter getTopics() {
public List<List<LogTopic>> getTopics() {
return topics;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters;

import org.hyperledger.besu.ethereum.api.query.TopicsParameter;
import static java.util.Collections.singletonList;

import org.hyperledger.besu.ethereum.core.LogTopic;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

import com.fasterxml.jackson.core.JsonParser;
Expand All @@ -26,7 +27,7 @@
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.google.common.collect.Lists;

public class TopicsDeserializer extends StdDeserializer<TopicsParameter> {
public class TopicsDeserializer extends StdDeserializer<List<List<LogTopic>>> {
public TopicsDeserializer() {
this(null);
}
Expand All @@ -36,27 +37,27 @@ public TopicsDeserializer(final Class<?> vc) {
}

@Override
public TopicsParameter deserialize(
public List<List<LogTopic>> deserialize(
final JsonParser jsonparser, final DeserializationContext context) throws IOException {
final JsonNode topicsNode = jsonparser.getCodec().readTree(jsonparser);
final List<List<String>> topics = Lists.newArrayList();
final List<List<LogTopic>> topics = Lists.newArrayList();

if (!topicsNode.isArray()) {
topics.add(Collections.singletonList(topicsNode.textValue()));
topics.add(singletonList(LogTopic.fromHexString(topicsNode.textValue())));
} else {
for (JsonNode child : topicsNode) {
if (child.isArray()) {
final List<String> childItems = Lists.newArrayList();
final List<LogTopic> childItems = Lists.newArrayList();
for (JsonNode subChild : child) {
childItems.add(subChild.textValue());
childItems.add(LogTopic.fromHexString(subChild.textValue()));
}
topics.add(childItems);
} else {
topics.add(Collections.singletonList(child.textValue()));
topics.add(singletonList(LogTopic.fromHexString(child.textValue())));
}
}
}

return new TopicsParameter(topics);
return topics;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Subscription build(
return new LogsSubscription(
subscriptionId,
connectionId,
Optional.ofNullable(request.getFilterParameter())
Optional.ofNullable(request.getLogsQuery())
.orElseThrow(IllegalArgumentException::new));
}
case SYNCING:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,21 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.logs;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.FilterParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.Subscription;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.request.SubscriptionType;
import org.hyperledger.besu.ethereum.api.query.LogsQuery;

public class LogsSubscription extends Subscription {

private final FilterParameter filterParameter;
private final LogsQuery logsQuery;

public LogsSubscription(
final Long subscriptionId, final String connectionId, final FilterParameter filterParameter) {
final Long subscriptionId, final String connectionId, final LogsQuery logsQuery) {
super(subscriptionId, connectionId, SubscriptionType.LOGS, Boolean.FALSE);
this.filterParameter = filterParameter;
this.logsQuery = logsQuery;
}

public LogsQuery getLogsQuery() {
return new LogsQuery.Builder()
.addresses(filterParameter.getAddresses())
.topics(filterParameter.getTopics())
.build();
return logsQuery;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,34 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.request;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.FilterParameter;
import org.hyperledger.besu.ethereum.api.query.LogsQuery;

import java.util.Objects;

public class SubscribeRequest {

private final SubscriptionType subscriptionType;
private final Boolean includeTransaction;
private final FilterParameter filterParameter;
private final LogsQuery logsQuery;
private final String connectionId;

public SubscribeRequest(
final SubscriptionType subscriptionType,
final FilterParameter filterParameter,
final LogsQuery logsQuery,
final Boolean includeTransaction,
final String connectionId) {
this.subscriptionType = subscriptionType;
this.includeTransaction = includeTransaction;
this.filterParameter = filterParameter;
this.logsQuery = logsQuery;
this.connectionId = connectionId;
}

public SubscriptionType getSubscriptionType() {
return subscriptionType;
}

public FilterParameter getFilterParameter() {
return filterParameter;
public LogsQuery getLogsQuery() {
return logsQuery;
}

public Boolean getIncludeTransaction() {
Expand All @@ -54,16 +54,9 @@ public String getConnectionId() {

@Override
public String toString() {
return "SubscribeRequest{"
+ "subscriptionType="
+ subscriptionType
+ ", includeTransaction="
+ includeTransaction
+ ", filterParameter="
+ filterParameter
+ ", connectionId="
+ connectionId
+ '}';
return String.format(
"SubscribeRequest{subscriptionType=%s, includeTransaction=%s, logsQuery=%s, connectionId=%s}",
subscriptionType, includeTransaction, logsQuery, connectionId);
}

@Override
Expand All @@ -77,12 +70,12 @@ public boolean equals(final Object o) {
final SubscribeRequest that = (SubscribeRequest) o;
return subscriptionType == that.subscriptionType
&& Objects.equals(includeTransaction, that.includeTransaction)
&& Objects.equals(filterParameter, that.filterParameter)
&& Objects.equals(logsQuery, that.logsQuery)
&& Objects.equals(connectionId, that.connectionId);
}

@Override
public int hashCode() {
return Objects.hash(subscriptionType, includeTransaction, filterParameter, connectionId);
return Objects.hash(subscriptionType, includeTransaction, logsQuery, connectionId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,11 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.request;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.FilterParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.methods.WebSocketRpcRequest;
import org.hyperledger.besu.ethereum.api.query.TopicsParameter;
import org.hyperledger.besu.ethereum.api.query.LogsQuery;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

public class SubscriptionRequestMapper {
Expand Down Expand Up @@ -77,31 +73,8 @@ private SubscribeRequest parseNewBlockHeadersRequest(

private SubscribeRequest parseLogsRequest(
final WebSocketRpcRequest request, final JsonRpcParameter parameter) {
final LogsSubscriptionParam logFilterParams =
parameter.required(request.getParams(), 1, LogsSubscriptionParam.class);
return new SubscribeRequest(
SubscriptionType.LOGS,
createFilterParameter(logFilterParams),
null,
request.getConnectionId());
}

private FilterParameter createFilterParameter(final LogsSubscriptionParam logFilterParams) {
final List<String> addresses = hasAddresses(logFilterParams);
final List<List<String>> topics = hasTopics(logFilterParams);
return new FilterParameter(null, null, addresses, new TopicsParameter(topics), null);
}

private List<String> hasAddresses(final LogsSubscriptionParam logFilterParams) {
return logFilterParams.address() != null && !logFilterParams.address().isEmpty()
? logFilterParams.address()
: Collections.emptyList();
}

private List<List<String>> hasTopics(final LogsSubscriptionParam logFilterParams) {
return logFilterParams.topics() != null && !logFilterParams.topics().isEmpty()
? Arrays.asList(logFilterParams.topics())
: Collections.emptyList();
final LogsQuery logsQuery = parameter.required(request.getParams(), 1, LogsQuery.class);
return new SubscribeRequest(SubscriptionType.LOGS, logsQuery, null, request.getConnectionId());
}

public UnsubscribeRequest mapUnsubscribeRequest(final JsonRpcRequest jsonRpcRequest)
Expand Down
Loading

0 comments on commit a48a2de

Please sign in to comment.