problem: eth_chainId is not available

This commit is contained in:
Igor Artamonov
2021-12-24 18:10:03 -05:00
parent 8526c2a3ee
commit f2b471c56f
13 changed files with 56 additions and 30 deletions

View File

@@ -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<ParsedCallDetails>): Mono<CallResult> {
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)

View File

@@ -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 {

View File

@@ -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()

View File

@@ -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) }
}
/**

View File

@@ -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)
}
}

View File

@@ -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<String> {
return allowedMethods.toSortedSet()
return allowedMethods.plus(hardcodedMethods).toSortedSet()
}
override fun isHardcoded(method: String): Boolean {

View File

@@ -104,7 +104,7 @@ class DefaultEthereumMethods(
}
}
override fun isAllowed(method: String): Boolean {
override fun isCallable(method: String): Boolean {
return allowedMethods.contains(method)
}

View File

@@ -32,7 +32,7 @@ open class DirectCallMethods(private val methods: Set<String>) : CallMethods {
return AlwaysQuorum()
}
override fun isAllowed(method: String): Boolean {
override fun isCallable(method: String): Boolean {
return methods.contains(method)
}

View File

@@ -82,7 +82,7 @@ class ManagedCallMethods(
}
}
override fun isAllowed(method: String): Boolean {
override fun isCallable(method: String): Boolean {
return allAllowed.contains(method)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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])

View File

@@ -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