eth_filter fix review comments and tests
This commit is contained in:
@@ -401,4 +401,18 @@ class UpstreamsConfigReaderSpec extends Specification {
|
||||
act.upstreams.get(0).role == UpstreamsConfig.UpstreamRole.PRIMARY
|
||||
act.upstreams.get(1).role == UpstreamsConfig.UpstreamRole.PRIMARY
|
||||
}
|
||||
|
||||
def "Parse node id"() {
|
||||
setup:
|
||||
def config = this.class.getClassLoader().getResourceAsStream("upstreams-node-id.yaml")
|
||||
when:
|
||||
def act = reader.read(config)
|
||||
then:
|
||||
act != null
|
||||
act.upstreams.size() == 2
|
||||
act.upstreams[0].nodeId == 1
|
||||
act.upstreams[0].id == "has_node_id"
|
||||
act.upstreams[1].nodeId == null
|
||||
act.upstreams[1].id == "has_no_node_id"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,6 +395,68 @@ class NativeCallSpec extends Specification {
|
||||
}
|
||||
}
|
||||
|
||||
def "Prepare call adds decorator for eth_newFilter"() {
|
||||
setup:
|
||||
def methods = new ManagedCallMethods(
|
||||
new DefaultEthereumMethods(Chain.ETHEREUM),
|
||||
["eth_newFilter"] as Set, [] as Set
|
||||
)
|
||||
methods.setQuorum("eth_newFilter", "always")
|
||||
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream())
|
||||
multistream.customMethods = methods
|
||||
multistream.customHead = Mock(Head)
|
||||
def multistreamHolder = Mock(MultistreamHolder) {
|
||||
_ * it.observeChains() >> Flux.empty()
|
||||
}
|
||||
def nativeCall = nativeCall(multistreamHolder)
|
||||
|
||||
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
||||
.setChain(Common.ChainRef.CHAIN_ETHEREUM)
|
||||
.addItems(
|
||||
BlockchainOuterClass.NativeCallItem.newBuilder()
|
||||
.setId(1)
|
||||
.setMethod("eth_newFilter")
|
||||
)
|
||||
.build()
|
||||
when:
|
||||
def act = nativeCall.prepareCall(req, multistream)
|
||||
.collectList().block(Duration.ofSeconds(1)).first()
|
||||
then:
|
||||
act instanceof NativeCall.ValidCallContext
|
||||
act.resultDecorator instanceof NativeCall.CreateFilterDecorator
|
||||
}
|
||||
|
||||
def "Prepare call adds decorator for eth_getFilterChanges"() {
|
||||
setup:
|
||||
def methods = new ManagedCallMethods(
|
||||
new DefaultEthereumMethods(Chain.ETHEREUM),
|
||||
["eth_getFilterChanges"] as Set, [] as Set
|
||||
)
|
||||
methods.setQuorum("eth_getFilterChanges", "always")
|
||||
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM, TestingCommons.upstream())
|
||||
multistream.customMethods = methods
|
||||
multistream.customHead = Mock(Head)
|
||||
def multistreamHolder = Mock(MultistreamHolder) {
|
||||
_ * it.observeChains() >> Flux.empty()
|
||||
}
|
||||
def nativeCall = nativeCall(multistreamHolder)
|
||||
|
||||
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
||||
.setChain(Common.ChainRef.CHAIN_ETHEREUM)
|
||||
.addItems(
|
||||
BlockchainOuterClass.NativeCallItem.newBuilder()
|
||||
.setId(1)
|
||||
.setMethod("eth_getFilterChanges")
|
||||
)
|
||||
.build()
|
||||
when:
|
||||
def act = nativeCall.prepareCall(req, multistream)
|
||||
.collectList().block(Duration.ofSeconds(1)).first()
|
||||
then:
|
||||
act instanceof NativeCall.ValidCallContext
|
||||
act.requestDecorator instanceof NativeCall.GetFilterUpdatesDecorator
|
||||
}
|
||||
|
||||
def "Parse empty params"() {
|
||||
setup:
|
||||
def nativeCall = nativeCall()
|
||||
@@ -447,6 +509,64 @@ class NativeCallSpec extends Specification {
|
||||
act.payload.method == "eth_test"
|
||||
}
|
||||
|
||||
def "Decorate eth_getFilterUpdates params"() {
|
||||
setup:
|
||||
def nativeCall = nativeCall()
|
||||
def ctx = new NativeCall.ValidCallContext(1, null, Stub(Multistream), Selector.empty, new AlwaysQuorum(),
|
||||
new NativeCall.RawCallDetails("eth_getFilterUpdates", '["0xabcd"]'),
|
||||
new NativeCall.GetFilterUpdatesDecorator(), new NativeCall.NoneResultDecorator())
|
||||
when:
|
||||
def act = nativeCall.parseParams(ctx)
|
||||
then:
|
||||
act.id == 1
|
||||
act.payload.params == ["0xab"]
|
||||
act.payload.method == "eth_getFilterUpdates"
|
||||
}
|
||||
|
||||
def "Decorate eth_newFilter result"() {
|
||||
setup:
|
||||
def quorum = new AlwaysQuorum()
|
||||
|
||||
def nativeCall = nativeCall()
|
||||
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
||||
1 * create(_, _, _) >> Mock(Reader) {
|
||||
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList((byte)255)))
|
||||
}
|
||||
}
|
||||
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
|
||||
new NativeCall.ParsedCallDetails("eth_getFilterChanges", []),
|
||||
new NativeCall.GetFilterUpdatesDecorator(), new NativeCall.CreateFilterDecorator())
|
||||
|
||||
when:
|
||||
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))
|
||||
def act = objectMapper.readValue(resp.result, Object)
|
||||
then:
|
||||
act == "0xabff"
|
||||
resp.nonce == 10
|
||||
}
|
||||
|
||||
def "Decorate eth_newFilter result with short nodeId"() {
|
||||
setup:
|
||||
def quorum = new AlwaysQuorum()
|
||||
|
||||
def nativeCall = nativeCall()
|
||||
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
||||
1 * create(_, _, _) >> Mock(Reader) {
|
||||
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList((byte)1)))
|
||||
}
|
||||
}
|
||||
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
|
||||
new NativeCall.ParsedCallDetails("eth_getFilterChanges", []),
|
||||
new NativeCall.GetFilterUpdatesDecorator(), new NativeCall.CreateFilterDecorator())
|
||||
|
||||
when:
|
||||
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))
|
||||
def act = objectMapper.readValue(resp.result, Object)
|
||||
then:
|
||||
act == "0xab01"
|
||||
resp.nonce == 10
|
||||
}
|
||||
|
||||
@Ignore
|
||||
//TODO
|
||||
def "Calls cache before remote"() {
|
||||
|
||||
@@ -58,4 +58,37 @@ class ConfiguredUpstreamsSpec extends Specification {
|
||||
act instanceof ManagedCallMethods
|
||||
new String(act.executeHardcoded("foo_bar")) == "\"static_response\""
|
||||
}
|
||||
|
||||
def "Calculate node-id"() {
|
||||
setup:
|
||||
def configurer = new ConfiguredUpstreams(Stub(CurrentMultistreamHolder), Stub(FileResolver), Stub(UpstreamsConfig)
|
||||
)
|
||||
expect:
|
||||
configurer.getHash(node, src) == expected
|
||||
|
||||
where:
|
||||
node | src | expected
|
||||
1 | "" | 1
|
||||
9 | "hohoho" | 9
|
||||
null | "hohoho" | 120
|
||||
}
|
||||
|
||||
def "Calculate node-id conflicting results"() {
|
||||
setup:
|
||||
def configurer = new ConfiguredUpstreams(Stub(CurrentMultistreamHolder), Stub(FileResolver), Stub(UpstreamsConfig)
|
||||
)
|
||||
when:
|
||||
def h1 = configurer.getHash(null, "hohoho")
|
||||
def h2 = configurer.getHash(null, "hohoho")
|
||||
def h3 = configurer.getHash(null, "hohoho")
|
||||
def h4 = configurer.getHash(null, "hohoho")
|
||||
def h5 = configurer.getHash(null, "hohoho")
|
||||
|
||||
then:
|
||||
h1 == (byte)120
|
||||
h2 == (byte)-120
|
||||
h3 == (byte)-9
|
||||
h4 == (byte)8
|
||||
h5 == (byte)-128
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,4 +349,27 @@ class SelectorSpec extends Specification {
|
||||
!act
|
||||
}
|
||||
|
||||
def "Matches same nodeId"() {
|
||||
setup:
|
||||
def up = Mock(Upstream) {
|
||||
nodeId() >> (byte)5
|
||||
}
|
||||
def matcher = new Selector.SameNodeMatcher((byte)5)
|
||||
when:
|
||||
def act = matcher.matches(up)
|
||||
then:
|
||||
act
|
||||
}
|
||||
|
||||
def "Not matches nodeId"() {
|
||||
setup:
|
||||
def up = Mock(Upstream) {
|
||||
nodeId() >> (byte)5
|
||||
}
|
||||
def matcher = new Selector.SameNodeMatcher((byte)1)
|
||||
when:
|
||||
def act = matcher.matches(up)
|
||||
then:
|
||||
!act
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,4 +179,22 @@ class EthereumCallSelectorSpec extends Specification {
|
||||
then:
|
||||
act == new Selector.HeightMatcher(100)
|
||||
}
|
||||
|
||||
def "Get same matcher for getFilterChanges method"() {
|
||||
setup:
|
||||
def callSelector = new EthereumCallSelector(Mock(Reader))
|
||||
def head = Mock(Head)
|
||||
|
||||
expect:
|
||||
callSelector.getMatcher("eth_getFilterChanges", param, head).block()
|
||||
== new Selector.SameNodeMatcher((byte)hash)
|
||||
|
||||
where:
|
||||
param | hash
|
||||
'["0xff09"]' | 9
|
||||
'["0xff"]' | 255
|
||||
'[]' | 0
|
||||
'[""]' | 0
|
||||
'["0x0"]' | 0
|
||||
}
|
||||
}
|
||||
|
||||
34
src/test/resources/upstreams-node-id.yaml
Normal file
34
src/test/resources/upstreams-node-id.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
version: v1
|
||||
upstreams:
|
||||
- id: has_node_id
|
||||
node-id: 1
|
||||
chain: ethereum
|
||||
connection:
|
||||
ethereum:
|
||||
rpc:
|
||||
url: "http://localhost:8545"
|
||||
- id: has_no_node_id
|
||||
chain: ethereum
|
||||
connection:
|
||||
ethereum:
|
||||
rpc:
|
||||
url: "http://localhost:8545"
|
||||
ws:
|
||||
url: "ws://localhost:8546"
|
||||
- id: conflicted_node_id
|
||||
node-id: 1
|
||||
chain: ethereum
|
||||
connection:
|
||||
prefer-http: true
|
||||
ethereum:
|
||||
rpc:
|
||||
url: "http://localhost:9545"
|
||||
ws:
|
||||
url: "ws://localhost:9546"
|
||||
- id: invalid_node_id
|
||||
node-id: 256
|
||||
chain: ethereum
|
||||
connection:
|
||||
grpc:
|
||||
host: "localhost"
|
||||
port: 2449
|
||||
Reference in New Issue
Block a user