Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

[PAN-2519] single topic filter #1235

Merged
merged 2 commits into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.MoreObjects;

public class FilterParameter {
Expand All @@ -38,14 +39,14 @@ public FilterParameter(
@JsonProperty("toBlock") final String toBlock,
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) @JsonProperty("address")
final List<String> address,
@JsonProperty("topics") final List<List<String>> topics,
@JsonDeserialize(using = TopicsDeserializer.class) @JsonProperty("topics")
final TopicsParameter 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 ? new TopicsParameter(topics) : new TopicsParameter(Collections.emptyList());
this.topics = topics != null ? topics : new TopicsParameter(Collections.emptyList());
this.blockhash = blockhash != null ? Hash.fromHexString(blockhash) : null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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.pantheon.ethereum.jsonrpc.internal.parameters;

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

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;

public class TopicsDeserializer extends StdDeserializer<TopicsParameter> {
public TopicsDeserializer() {
this(null);
}

public TopicsDeserializer(final Class<?> vc) {
super(vc);
}

@Override
public TopicsParameter deserialize(
final JsonParser jsonparser, final DeserializationContext context) throws IOException {
List<String> topicsList = new ArrayList<>();

try {
// try standard method
return jsonparser.readValueAs(TopicsParameter.class);
} catch (MismatchedInputException mie) {
// is there a single string value instead of expected list of list
String topics = jsonparser.getText();
if (topics == null) {
return new TopicsParameter(Collections.singletonList(topicsList));
} else {
// make it list of list
return new TopicsParameter(Collections.singletonList(Collections.singletonList(topics)));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.FilterParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.TopicsParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.UnsignedLongParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.methods.WebSocketRpcRequest;

Expand Down Expand Up @@ -81,7 +82,7 @@ private SubscribeRequest parseLogsRequest(
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, topics, null);
return new FilterParameter(null, null, addresses, new TopicsParameter(topics), null);
}

private List<String> hasAddresses(final LogsSubscriptionParam logFilterParams) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ private List<List<String>> topics() {
private FilterParameter filterParamWithAddressAndTopics(
final Address address, final List<List<String>> topics) {
final List<String> addresses = address != null ? Arrays.asList(address.toString()) : null;
return new FilterParameter("latest", "latest", addresses, topics, null);
return new FilterParameter("latest", "latest", addresses, new TopicsParameter(topics), null);
}

private JsonRpcRequest ethNewFilter(final FilterParameter filterParameter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
Expand Down Expand Up @@ -53,10 +55,84 @@ public void jsonWithSingleAddressShouldSerializeSuccessfully() throws Exception
.isEqualToComparingFieldByFieldRecursively(expectedFilterParameter);
}

@Test
public void jsonWithSingleAddressAndSingleTopicShouldSerializeSuccessfully() throws Exception {
final String jsonWithSingleAddress =
"{\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{\"address\":\"0x0\", \"topics\":\"0x0000000000000000000000000000000000000000000000000000000000000002\" }],\"id\":1}";

final JsonRpcRequest request = readJsonAsJsonRpcRequest(jsonWithSingleAddress);
final FilterParameter expectedFilterParameter =
filterParameterWithAddressAndSingleListOfTopics(
"0x0", "0x0000000000000000000000000000000000000000000000000000000000000002");

final FilterParameter parsedFilterParameter =
parameters.required(request.getParams(), 0, FilterParameter.class);

assertThat(parsedFilterParameter)
.isEqualToComparingFieldByFieldRecursively(expectedFilterParameter);
}

@Test
public void jsonWithSingleAddressAndMultipleTopicsShouldSerializeSuccessfully() throws Exception {
final String jsonWithSingleAddress =
"{\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{\"address\":\"0x0\", \"topics\":[[\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\"]]}],\"id\":1}";

final JsonRpcRequest request = readJsonAsJsonRpcRequest(jsonWithSingleAddress);
final FilterParameter expectedFilterParameter =
filterParameterWithAddressAndSingleListOfTopics(
"0x0",
"0x0000000000000000000000000000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000000000000000000000000000003");

final FilterParameter parsedFilterParameter =
parameters.required(request.getParams(), 0, FilterParameter.class);

assertThat(parsedFilterParameter)
.isEqualToComparingFieldByFieldRecursively(expectedFilterParameter);
}

@Test
public void jsonWithSingleAddressAndMultipleListsOfTopicsShouldSerializeSuccessfully()
throws Exception {
final String jsonWithSingleAddress =
"{\"jsonrpc\":\"2.0\",\"method\":\"eth_getLogs\",\"params\":[{\"address\":\"0x0\", \"topics\":[[\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\"],[\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\"]]}],\"id\":1}";

final JsonRpcRequest request = readJsonAsJsonRpcRequest(jsonWithSingleAddress);
final FilterParameter expectedFilterParameter =
filterParameterWithAddressAndMultipleListOfTopics(
"0x0",
"0x0000000000000000000000000000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000000000000000000000000000003");

final FilterParameter parsedFilterParameter =
parameters.required(request.getParams(), 0, FilterParameter.class);

assertThat(parsedFilterParameter)
.isEqualToComparingFieldByFieldRecursively(expectedFilterParameter);
}

private FilterParameter filterParameterWithAddresses(final String... addresses) {
return new FilterParameter("latest", "latest", Arrays.asList(addresses), null, null);
}

private FilterParameter filterParameterWithAddressAndSingleListOfTopics(
final String address, final String... topics) {
return new FilterParameter(
"latest",
"latest",
Arrays.asList(address),
new TopicsParameter(Collections.singletonList(Arrays.asList(topics))),
null);
}

private FilterParameter filterParameterWithAddressAndMultipleListOfTopics(
final String address, final String... topics) {
List<String> topicsList = Arrays.asList(topics);
List<List<String>> topicsListList = Arrays.asList(topicsList, topicsList);
return new FilterParameter(
"latest", "latest", Arrays.asList(address), new TopicsParameter(topicsListList), null);
}

private JsonRpcRequest readJsonAsJsonRpcRequest(final String jsonWithSingleAddress)
throws java.io.IOException {
return new ObjectMapper().readValue(jsonWithSingleAddress, JsonRpcRequest.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.FilterParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.TopicsParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.methods.WebSocketRpcRequest;

import java.util.Arrays;
Expand Down Expand Up @@ -160,7 +161,7 @@ public void mapRequestWithSingleAddress() {
null,
null,
Arrays.asList("0x8320fe7702b96808f7bbc0d4a888ed1468216cfd"),
Collections.emptyList(),
new TopicsParameter(Collections.emptyList()),
null);
final SubscribeRequest expectedSubscribeRequest =
new SubscribeRequest(SubscriptionType.LOGS, expectedFilterParam, null, null);
Expand All @@ -184,9 +185,10 @@ public void mapRequestWithMultipleAddresses() {
Arrays.asList(
"0x8320fe7702b96808f7bbc0d4a888ed1468216cfd",
"0xf17f52151EbEF6C7334FAD080c5704D77216b732"),
Arrays.asList(
new TopicsParameter(
Arrays.asList(
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902")),
Arrays.asList(
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"))),
null);
final SubscribeRequest expectedSubscribeRequest =
new SubscribeRequest(SubscriptionType.LOGS, expectedFilterParam, null, null);
Expand All @@ -208,10 +210,11 @@ public void mapRequestWithMultipleTopics() {
null,
null,
Arrays.asList("0x8320fe7702b96808f7bbc0d4a888ed1468216cfd"),
Arrays.asList(
new TopicsParameter(
Arrays.asList(
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902",
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab901")),
Arrays.asList(
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902",
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab901"))),
null);
final SubscribeRequest expectedSubscribeRequest =
new SubscribeRequest(SubscriptionType.LOGS, expectedFilterParam, null, null);
Expand All @@ -233,7 +236,7 @@ public void mapRequestToLogsWithoutTopics() {
null,
null,
Arrays.asList("0x8320fe7702b96808f7bbc0d4a888ed1468216cfd"),
Collections.emptyList(),
new TopicsParameter(Collections.emptyList()),
null);
final SubscribeRequest expectedSubscribeRequest =
new SubscribeRequest(SubscriptionType.LOGS, expectedFilterParam, null, null);
Expand Down