From acdb450fdf388bdf7183ee6d43367ffa678d47f0 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Wed, 17 Nov 2021 21:39:17 -0500 Subject: [PATCH] problem: doesn't use hardcoded methods on Bitcoin --- .../upstream/bitcoin/BitcoinMultistream.kt | 4 +- .../upstream/bitcoin/LocalCallRouter.kt | 53 +++++++++++++++++++ .../upstream/ethereum/EthereumMultistream.kt | 2 +- ...NativeCallRouter.kt => LocalCallRouter.kt} | 4 +- ...Spec.groovy => LocalCallRouterSpec.groovy} | 10 ++-- 5 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt rename src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/{NativeCallRouter.kt => LocalCallRouter.kt} (98%) rename src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/{NativeCallRouterSpec.groovy => LocalCallRouterSpec.groovy} (92%) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt index 568562da..0fa067ca 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt @@ -26,6 +26,7 @@ import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.RequestPostprocessor import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Upstream +import io.emeraldpay.dshackle.upstream.ethereum.LocalCallRouter import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.grpc.Chain @@ -86,8 +87,7 @@ open class BitcoinMultistream( } override fun getRoutedApi(matcher: Selector.Matcher): Mono> { - // TODO - return Mono.just(EmptyReader()) + return Mono.just(LocalCallRouter(getMethods())) } open fun getReader(): BitcoinReader { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt new file mode 100644 index 00000000..1b67a846 --- /dev/null +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2021 EmeraldPay, Inc + * + * 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 io.emeraldpay.dshackle.upstream.bitcoin + +import io.emeraldpay.dshackle.reader.Reader +import io.emeraldpay.dshackle.upstream.calls.CallMethods +import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.etherjar.rpc.RpcException +import io.emeraldpay.etherjar.rpc.RpcResponseError +import org.slf4j.LoggerFactory +import reactor.core.publisher.Mono + +/** + * Reader for JSON RPC requests. Verifies if the method is allowed, transforms if necessary, and calls EthereumReader for data. + * It provides data only if it's available through the router (cached, head, etc). + * If data is not available locally then it returns `empty`; at this case the caller should call the remote node for actual data. + * + * @see BitcoinReader + */ +class LocalCallRouter( + private val methods: CallMethods, +) : Reader { + + companion object { + private val log = LoggerFactory.getLogger(LocalCallRouter::class.java) + } + + override fun read(key: JsonRpcRequest): Mono { + 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")) + } + return Mono.empty() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt index 484e3881..78151a62 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt @@ -124,7 +124,7 @@ open class EthereumMultistream( } override fun getRoutedApi(matcher: Selector.Matcher): Mono> { - return Mono.just(NativeCallRouter(reader, getMethods(), getHead())) + return Mono.just(LocalCallRouter(reader, getMethods(), getHead())) } open fun getSubscribe(): EthereumSubscribe { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt similarity index 98% rename from src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt rename to src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt index 3808d1d9..2077692f 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouter.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouter.kt @@ -36,14 +36,14 @@ import java.math.BigInteger * * @see EthereumReader */ -class NativeCallRouter( +class LocalCallRouter( private val reader: EthereumReader, private val methods: CallMethods, private val head: Head ) : Reader { companion object { - private val log = LoggerFactory.getLogger(NativeCallRouter::class.java) + private val log = LoggerFactory.getLogger(LocalCallRouter::class.java) } private val fullBlocksReader = EthereumFullBlocksReader( diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouterSpec.groovy similarity index 92% rename from src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy rename to src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouterSpec.groovy index 2e150cb0..2865fde1 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/NativeCallRouterSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/LocalCallRouterSpec.groovy @@ -17,12 +17,12 @@ import spock.lang.Specification import java.time.Duration -class NativeCallRouterSpec extends Specification { +class LocalCallRouterSpec extends Specification { def "Calls hardcoded"() { setup: def methods = new DefaultEthereumMethods(Chain.ETHEREUM) - def router = new NativeCallRouter( + def router = new LocalCallRouter( new EthereumReader( TestingCommons.multistream(TestingCommons.api()), Caches.default(), @@ -50,7 +50,7 @@ class NativeCallRouterSpec extends Specification { } } def methods = new DefaultEthereumMethods(Chain.ETHEREUM) - def router = new NativeCallRouter(reader, methods, head) + def router = new LocalCallRouter(reader, methods, head) when: def act = router.getBlockByNumber(["latest", false]) @@ -76,7 +76,7 @@ class NativeCallRouterSpec extends Specification { } } def methods = new DefaultEthereumMethods(Chain.ETHEREUM) - def router = new NativeCallRouter(reader, methods, head) + def router = new LocalCallRouter(reader, methods, head) when: def act = router.getBlockByNumber(["earliest", false]) @@ -102,7 +102,7 @@ class NativeCallRouterSpec extends Specification { } } def methods = new DefaultEthereumMethods(Chain.ETHEREUM) - def router = new NativeCallRouter(reader, methods, head) + def router = new LocalCallRouter(reader, methods, head) when: def act = router.getBlockByNumber(["0x123ef", false])