From f2b471c56f12d36db3d8116f7198fa8e540344a9 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Fri, 24 Dec 2021 18:10:03 -0500 Subject: [PATCH] problem: eth_chainId is not available --- .../io/emeraldpay/dshackle/rpc/NativeCall.kt | 4 ++-- .../emeraldpay/dshackle/upstream/Selector.kt | 2 +- .../upstream/bitcoin/LocalCallRouter.kt | 2 +- .../upstream/calls/AggregatedCallMethods.kt | 6 +++--- .../dshackle/upstream/calls/CallMethods.kt | 15 +++++++++++++-- .../upstream/calls/DefaultBitcoinMethods.kt | 6 +++--- .../upstream/calls/DefaultEthereumMethods.kt | 2 +- .../upstream/calls/DirectCallMethods.kt | 2 +- .../upstream/calls/ManagedCallMethods.kt | 2 +- .../upstream/ethereum/LocalCallRouter.kt | 2 +- .../dshackle/upstream/MultistreamSpec.groovy | 6 +++--- .../calls/AggregatedCallMethodsSpec.groovy | 19 ++++++++----------- .../calls/DefaultEthereumMethodsSpec.groovy | 18 ++++++++++++++++++ 13 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index 6b75b14f..a159ac7d 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -163,7 +163,7 @@ open class NativeCall( val params = requestItem.payload.toStringUtf8() val availableMethods = upstream.getMethods() - if (!availableMethods.isAllowed(method)) { + if (!availableMethods.isAvailable(method)) { val errorMessage = "The method $method does not exist/is not available" return Mono.just( InvalidCallContext( @@ -222,7 +222,7 @@ open class NativeCall( } fun executeOnRemote(ctx: ValidCallContext): Mono { - if (!ctx.upstream.getMethods().isAllowed(ctx.payload.method)) { + if (!ctx.upstream.getMethods().isCallable(ctx.payload.method)) { return Mono.error(RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Unsupported method")) } val reader = quorumReaderFactory.create(ctx.getApis(), ctx.callQuorum) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt index 50a1365f..4f57a7f3 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt @@ -157,7 +157,7 @@ class Selector { val method: String ) : Matcher { override fun matches(up: Upstream): Boolean { - return up.getMethods().isAllowed(method) + return up.getMethods().isCallable(method) } override fun describeInternal(): String { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt index a6cafef6..5f77cfca 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt @@ -44,7 +44,7 @@ class LocalCallRouter( return Mono.just(methods.executeHardcoded(key.method)) .map { JsonRpcResponse(it, null) } } - if (!methods.isAllowed(key.method)) { + if (!methods.isCallable(key.method)) { return Mono.error(RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Unsupported method")) } return Mono.empty() 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 9df4084b..eae9f0b7 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethods.kt @@ -39,15 +39,15 @@ class AggregatedCallMethods( */ override fun getQuorumFor(method: String): CallQuorum { return delegates.find { - it.isAllowed(method) || it.isHardcoded(method) + it.isCallable(method) || it.isHardcoded(method) }?.getQuorumFor(method) ?: throw IllegalStateException("No executor delegate for $method") } /** * Checks if ANY of delegates supports the method */ - override fun isAllowed(method: String): Boolean { - return delegates.any { it.isAllowed(method) } + override fun isCallable(method: String): Boolean { + return delegates.any { it.isCallable(method) } } /** diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/CallMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/CallMethods.kt index 1b2b80f9..d0abc4fa 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/CallMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/CallMethods.kt @@ -29,9 +29,13 @@ interface CallMethods { fun getQuorumFor(method: String): CallQuorum /** - * @return false is call for that method is not allowed. Allowed method may be also Hardcoded + * Check if the method can be called on an upstream. Doesn't include Hardcoded methods + * + * @return false if call for that method is not allowed. + * @see isHardcoded + * @see isAvailable */ - fun isAllowed(method: String): Boolean + fun isCallable(method: String): Boolean /** * @return list of all allowed methods. @@ -47,4 +51,11 @@ interface CallMethods { * Read [supposed to be predefined] method from this config */ fun executeHardcoded(method: String): ByteArray + + /** + * Check if the method is available either by an upstream or as a hardcoded response + */ + fun isAvailable(method: String): Boolean { + return isCallable(method) || isHardcoded(method) + } } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultBitcoinMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultBitcoinMethods.kt index da43e930..35ce7939 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultBitcoinMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultBitcoinMethods.kt @@ -57,7 +57,7 @@ class DefaultBitcoinMethods : CallMethods { ).sorted() private val allowedMethods = - (freshMethods + anyResponseMethods + headVerifiedMethods + hardcodedMethods + broadcastMethods).sorted() + (freshMethods + anyResponseMethods + headVerifiedMethods + broadcastMethods).sorted() override fun getQuorumFor(method: String): CallQuorum { return when { @@ -70,12 +70,12 @@ class DefaultBitcoinMethods : CallMethods { } } - override fun isAllowed(method: String): Boolean { + override fun isCallable(method: String): Boolean { return Collections.binarySearch(allowedMethods, method) >= 0 } override fun getSupportedMethods(): Set { - return allowedMethods.toSortedSet() + return allowedMethods.plus(hardcodedMethods).toSortedSet() } override fun isHardcoded(method: String): Boolean { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt index c1e0557b..6547d138 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt @@ -104,7 +104,7 @@ class DefaultEthereumMethods( } } - override fun isAllowed(method: String): Boolean { + override fun isCallable(method: String): Boolean { return allowedMethods.contains(method) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DirectCallMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DirectCallMethods.kt index a087e5f4..0f46d376 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DirectCallMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DirectCallMethods.kt @@ -32,7 +32,7 @@ open class DirectCallMethods(private val methods: Set) : CallMethods { return AlwaysQuorum() } - override fun isAllowed(method: String): Boolean { + override fun isCallable(method: String): Boolean { return methods.contains(method) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/ManagedCallMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/ManagedCallMethods.kt index 38d09ae0..0e36c6f9 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/ManagedCallMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/ManagedCallMethods.kt @@ -82,7 +82,7 @@ class ManagedCallMethods( } } - override fun isAllowed(method: String): Boolean { + override fun isCallable(method: String): Boolean { return allAllowed.contains(method) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt index 2077692f..ebe530c3 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt @@ -56,7 +56,7 @@ class LocalCallRouter( return Mono.just(methods.executeHardcoded(key.method)) .map { JsonRpcResponse(it, null) } } - if (!methods.isAllowed(key.method)) { + if (!methods.isCallable(key.method)) { return Mono.error(RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Unsupported method")) } val common = commonRequests(key) diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/MultistreamSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/MultistreamSpec.groovy index 60331c22..60e53174 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/MultistreamSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/MultistreamSpec.groovy @@ -45,9 +45,9 @@ class MultistreamSpec extends Specification { aggr.onUpstreamsUpdated() def act = aggr.getMethods() then: - act.isAllowed("eth_test1") - act.isAllowed("eth_test2") - act.isAllowed("eth_test3") + act.isCallable("eth_test1") + act.isCallable("eth_test2") + act.isCallable("eth_test3") act.getQuorumFor("eth_test1") instanceof AlwaysQuorum act.getQuorumFor("eth_test2") instanceof AlwaysQuorum act.getQuorumFor("eth_test3") instanceof AlwaysQuorum 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 c11149fc..2109feae 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethodsSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/AggregatedCallMethodsSpec.groovy @@ -17,9 +17,6 @@ package io.emeraldpay.dshackle.upstream.calls import io.emeraldpay.dshackle.quorum.AlwaysQuorum -import io.emeraldpay.dshackle.upstream.calls.AggregatedCallMethods -import io.emeraldpay.dshackle.upstream.calls.CallMethods -import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods import spock.lang.Specification class AggregatedCallMethodsSpec extends Specification { @@ -29,11 +26,11 @@ class AggregatedCallMethodsSpec extends Specification { def quorum = new AlwaysQuorum() def delegate1 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_no_test", "foo_bar"] - 1 * isAllowed("eth_test") >> false + 1 * isCallable("eth_test") >> false } def delegate2 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_test", "foo_bar"] - 1 * isAllowed("eth_test") >> true + 1 * isCallable("eth_test") >> true 1 * getQuorumFor("eth_test") >> quorum } def aggregate = new AggregatedCallMethods([delegate1, delegate2]) @@ -49,22 +46,22 @@ class AggregatedCallMethodsSpec extends Specification { def delegate2 = new DirectCallMethods(["eth_test", "foo_bar"] as Set) def aggregate = new AggregatedCallMethods([delegate1, delegate2]) when: - def act = aggregate.isAllowed("eth_test") + def act = aggregate.isCallable("eth_test") then: act when: - act = aggregate.isAllowed("eth_no_test") + act = aggregate.isCallable("eth_no_test") then: act when: - act = aggregate.isAllowed("foo_bar") + act = aggregate.isCallable("foo_bar") then: act when: - act = aggregate.isAllowed("nothing") + act = aggregate.isCallable("nothing") then: !act } @@ -106,12 +103,12 @@ class AggregatedCallMethodsSpec extends Specification { setup: def delegate1 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_no_test", "foo_bar"] - _ * isAllowed(_) >> false + _ * isCallable(_) >> false 1 * isHardcoded("eth_no_test") >> false } def delegate2 = Mock(CallMethods) { _ * getSupportedMethods() >> ["eth_test", "foo_bar"] - _ * isAllowed(_) >> false + _ * isCallable(_) >> false 1 * isHardcoded("eth_test") >> true } def aggregate = new AggregatedCallMethods([delegate1, delegate2]) diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy index 46cb5211..e58d3baf 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethodsSpec.groovy @@ -5,6 +5,15 @@ import spock.lang.Specification class DefaultEthereumMethodsSpec extends Specification { + def "eth_chainId is available"() { + setup: + def methods = new DefaultEthereumMethods(Chain.ETHEREUM) + when: + def act = methods.isAvailable("eth_chainId") + then: + act + } + def "eth_chainId is hardcoded"() { setup: def methods = new DefaultEthereumMethods(Chain.ETHEREUM) @@ -14,6 +23,15 @@ class DefaultEthereumMethodsSpec extends Specification { act } + def "eth_chainId is not callable"() { + setup: + def methods = new DefaultEthereumMethods(Chain.ETHEREUM) + when: + def act = methods.isCallable("eth_chainId") + then: + !act + } + def "Provides hardcoded correct chainId"() { expect: new String(new DefaultEthereumMethods(chain).executeHardcoded("eth_chainId")) == id