From af4aba69e74cbba3e045721e1b22c811aabce93d Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Thu, 14 May 2020 22:37:46 -0400 Subject: [PATCH] problem: hardcoded methods are not called --- .../upstream/calls/AggregatedCallMethods.kt | 6 ++-- .../upstream/ethereum/NativeCallRouter.kt | 8 ++--- .../calls/AggregatedCallMethodsSpec.groovy | 31 +++++++++++++---- .../ethereum/NativeCallRouterSpec.groovy | 34 +++++++++++++++++++ 4 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethods.kt index 29fd2548..3739bd1b 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethods.kt @@ -40,7 +40,7 @@ class AggregatedCallMethods( */ override fun getQuorumFor(method: String): CallQuorum { return delegates.find { - it.isAllowed(method) + it.isAllowed(method) || it.isHardcoded(method) }?.getQuorumFor(method) ?: throw IllegalStateException("No quorum for $method") } @@ -62,7 +62,7 @@ class AggregatedCallMethods( * @return true if there is at least one delegate that allows the method and it's hardcoded on that delegate */ override fun isHardcoded(method: String): Boolean { - return delegates.any { it.isAllowed(method) && it.isHardcoded(method) } + return delegates.any { it.isHardcoded(method) } } /** @@ -70,7 +70,7 @@ class AggregatedCallMethods( */ override fun executeHardcoded(method: String): ByteArray { return delegates.find { - it.isAllowed(method) && it.isHardcoded(method) + it.isHardcoded(method) }?.executeHardcoded(method) ?: throw IllegalStateException("No hardcoded for $method") } } \ No newline at end of file diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt index f3ad5207..22afa79d 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt @@ -47,18 +47,18 @@ class NativeCallRouter( ) override fun read(key: JsonRpcRequest): Mono { - if (!methods.isAllowed(key.method)) { - return Mono.error(RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Unsupported method")) - } if (methods.isHardcoded(key.method)) { return Mono.just(methods.executeHardcoded(key.method)) .map { JsonRpcResponse(it, null) } } + if (!methods.isAllowed(key.method)) { + return Mono.error(RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Unsupported method")) + } val common = commonRequests(key) if (common != null) { return common.map { JsonRpcResponse(it, null) } } - return directApi.read(key) + return Mono.empty() } /** diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethodsSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethodsSpec.groovy index ea465bdd..c11149fc 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethodsSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethodsSpec.groovy @@ -84,16 +84,34 @@ class AggregatedCallMethodsSpec extends Specification { setup: def delegate1 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_no_test", "foo_bar"] - 1 * isAllowed("eth_test") >> false - 1 * isAllowed("eth_no_test") >> true - 1 * isHardcoded("eth_no_test") >> false } def delegate2 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_test", "foo_bar"] - 1 * isAllowed("eth_test") >> true - 1 * isAllowed("eth_no_test") >> false + 1 * isHardcoded("eth_test") >> true + } + def aggregate = new AggregatedCallMethods([delegate1, delegate2]) + when: + def act = aggregate.isHardcoded("eth_test") + then: + act + when: + act = aggregate.isHardcoded("eth_no_test") + then: + !act + } + + def "Can be hardcoded if not allowed"() { + setup: + def delegate1 = Mock(CallMethods) { + _ * getSupportedMethods() >> ["eth_no_test", "foo_bar"] + _ * isAllowed(_) >> false + 1 * isHardcoded("eth_no_test") >> false + } + def delegate2 = Mock(CallMethods) { + _ * getSupportedMethods() >> ["eth_test", "foo_bar"] + _ * isAllowed(_) >> false 1 * isHardcoded("eth_test") >> true } def aggregate = new AggregatedCallMethods([delegate1, delegate2]) @@ -112,11 +130,10 @@ class AggregatedCallMethodsSpec extends Specification { setup: def delegate1 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_no_test", "foo_bar"] - 1 * isAllowed("eth_test") >> false + 1 * isHardcoded("eth_test") >> false } def delegate2 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_test", "foo_bar"] - 1 * isAllowed("eth_test") >> true 1 * isHardcoded("eth_test") >> true 1 * executeHardcoded("eth_test") >> "hello" } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy new file mode 100644 index 00000000..712bb047 --- /dev/null +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy @@ -0,0 +1,34 @@ +package io.emeraldpay.dshackle.upstream.ethereum + +import io.emeraldpay.dshackle.cache.Caches +import io.emeraldpay.dshackle.reader.EmptyReader +import io.emeraldpay.dshackle.test.TestingCommons +import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods +import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.grpc.Chain +import spock.lang.Specification + +import java.time.Duration + +class NativeCallRouterSpec extends Specification { + + def "Calls hardcoded"() { + setup: + def methods = new DefaultEthereumMethods(TestingCommons.objectMapper(), Chain.ETHEREUM) + def router = new NativeCallRouter( + TestingCommons.objectMapper(), + new EthereumReader( + TestingCommons.aggregatedUpstream(TestingCommons.api()), + Caches.default(TestingCommons.objectMapper()), + TestingCommons.objectMapper() + ), + new EmptyReader(), + methods + ) + when: + def act = router.read(new JsonRpcRequest("eth_coinbase", [])).block(Duration.ofSeconds(1)) + then: + act.resultAsProcessedString == "0x0000000000000000000000000000000000000000" + } +}