From 9c37831a5cc92c0f0ac6c636cf9ea51348bb7740 Mon Sep 17 00:00:00 2001 From: Igor Artamonov Date: Sun, 9 Jun 2019 16:46:19 -0400 Subject: [PATCH] solution: hardcode some methods for ethereum --- .../io/emeraldpay/dshackle/rpc/NativeCall.kt | 24 +---- .../dshackle/upstream/EthereumUpstream.kt | 96 ++++++++++++++++++- .../emeraldpay/dshackle/upstream/Upstreams.kt | 11 ++- 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index ce253a0d..59afd3a7 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -23,29 +23,7 @@ class NativeCall( private val log = LoggerFactory.getLogger(NativeCall::class.java) - private val allowedMethods = listOf( - "eth_gasPrice", - "eth_blockNumber", - "eth_getBalance", - "eth_getStorageAt", - "eth_getTransactionCount", - "eth_getBlockTransactionCountByHash", - "eth_getBlockTransactionCountByNumber", - "eth_getUncleCountByBlockHash", - "eth_getUncleCountByBlockNumber", - "eth_getCode", - "eth_sendRawTransaction", - "eth_call", - "eth_estimateGas", - "eth_getBlockByHash", - "eth_getBlockByNumber", - "eth_getTransactionByHash", - "eth_getTransactionByBlockHashAndIndex", - "eth_getTransactionByBlockNumberAndIndex", - "eth_getTransactionReceipt", - "eth_getUncleByBlockHashAndIndex", - "eth_getUncleByBlockNumberAndIndex" - ) + open fun nativeCall(request: BlockchainOuterClass.CallBlockchainRequest, responseObserver: StreamObserver) { val chain= Chain.byId(request.chain.number) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/EthereumUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/EthereumUpstream.kt index 497be8e3..9a19ac6b 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/EthereumUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/EthereumUpstream.kt @@ -1,29 +1,75 @@ package io.emeraldpay.dshackle.upstream import com.fasterxml.jackson.databind.ObjectMapper +import io.emeraldpay.grpc.Chain import io.infinitape.etherjar.rpc.RpcCall import io.infinitape.etherjar.rpc.RpcClient import io.infinitape.etherjar.rpc.RpcException -import io.infinitape.etherjar.rpc.RpcResponseError import io.infinitape.etherjar.rpc.json.ResponseJson import org.slf4j.LoggerFactory import reactor.core.publisher.Mono import java.time.Duration +import java.util.* class EthereumUpstream( private val rpcClient: RpcClient, - private val objectMapper: ObjectMapper + private val objectMapper: ObjectMapper, + private val chain: Chain ) { private val timeout = Duration.ofSeconds(5) private val log = LoggerFactory.getLogger(EthereumUpstream::class.java) + private val allowedMethods = listOf( + "eth_gasPrice", + "eth_blockNumber", + "eth_getBalance", + "eth_getStorageAt", + "eth_getTransactionCount", + "eth_getBlockTransactionCountByHash", + "eth_getBlockTransactionCountByNumber", + "eth_getUncleCountByBlockHash", + "eth_getUncleCountByBlockNumber", + "eth_getCode", + "eth_sendRawTransaction", + "eth_call", + "eth_estimateGas", + "eth_getBlockByHash", + "eth_getBlockByNumber", + "eth_getTransactionByHash", + "eth_getTransactionByBlockHashAndIndex", + "eth_getTransactionByBlockNumberAndIndex", + "eth_getTransactionReceipt", + "eth_getUncleByBlockHashAndIndex", + "eth_getUncleByBlockNumberAndIndex" + ) + + private val hardcodedMethods = listOf( + "net_version", + "net_peerCount", + "net_listening", + "web3_clientVersion", + "eth_protocolVersion", + "eth_syncing", + "eth_coinbase", + "eth_mining", + "eth_hashrate", + "eth_accounts" + ) + fun execute(id: Int, method: String, params: List): Mono { - return Mono - .fromCompletionStage( + val result: Mono = if (hardcodedMethods.contains(method)) { + Mono.just(method) + .map{ hardcoded(it) } + } else if (allowedMethods.contains(method)) { + Mono.fromCompletionStage( rpcClient.execute(RpcCall.create(method, Any::class.java, params)) ) .timeout(timeout) + } else { + Mono.error(RpcException(-32601, "Method not allowed or not found")) + } + return result .doOnError { t -> log.warn("Upstream error: ${t.message}") } @@ -49,4 +95,46 @@ class EthereumUpstream( } } + fun hardcoded(method: String): Any { + if ("net_version" == method) { + if (Chain.ETHEREUM == chain) { + return "1" + } + if (Chain.ETHEREUM_CLASSIC == chain) { + return "1" + } + if (Chain.MORDEN == chain) { + return "2" + } + throw RpcException(-32602, "Invalid chain") + } + if ("net_peerCount" == method) { + return "0x2a" + } + if ("net_listening" == method) { + return true + } + if ("web3_clientVersion" == method) { + return "EmeraldDshackle/v0.1" + } + if ("eth_protocolVersion" == method) { + return "0x3f" + } + if ("eth_syncing" == method) { + return false + } + if ("eth_coinbase" == method) { + return "0x0000000000000000000000000000000000000000" + } + if ("eth_mining" == method) { + return "false" + } + if ("eth_hashrate" == method) { + return "0x0" + } + if ("eth_accounts" == method) { + return Collections.emptyList() + } + throw RpcException(-32601, "Method not found") + } } \ No newline at end of file diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Upstreams.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Upstreams.kt index 507480d2..592a3535 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Upstreams.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Upstreams.kt @@ -22,20 +22,21 @@ class Upstreams( @PostConstruct fun start() { env.getProperty("upstream.ethereum")?.let { - chainMapping[Chain.ETHEREUM] = listOf(buildClient(it)) + chainMapping[Chain.ETHEREUM] = listOf(buildClient(it, Chain.ETHEREUM)) } env.getProperty("upstream.ethereumclassic")?.let { - chainMapping[Chain.ETHEREUM_CLASSIC] = listOf(buildClient(it)) + chainMapping[Chain.ETHEREUM_CLASSIC] = listOf(buildClient(it, Chain.ETHEREUM_CLASSIC)) } env.getProperty("upstream.morden")?.let { - chainMapping[Chain.MORDEN] = listOf(buildClient(it)) + chainMapping[Chain.MORDEN] = listOf(buildClient(it, Chain.MORDEN)) } } - private fun buildClient(url: String): EthereumUpstream { + private fun buildClient(url: String, chain: Chain): EthereumUpstream { return EthereumUpstream( DefaultRpcClient(DefaultRpcTransport(URI(url))), - objectMapper + objectMapper, + chain ) }