solution: hardcode some methods for ethereum

This commit is contained in:
Igor Artamonov
2019-06-09 16:46:19 -04:00
parent 69984871a1
commit 9c37831a5c
3 changed files with 99 additions and 32 deletions

View File

@@ -23,29 +23,7 @@ class NativeCall(
private val log = LoggerFactory.getLogger(NativeCall::class.java) 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<BlockchainOuterClass.CallBlockchainReplyItem>) { open fun nativeCall(request: BlockchainOuterClass.CallBlockchainRequest, responseObserver: StreamObserver<BlockchainOuterClass.CallBlockchainReplyItem>) {
val chain= Chain.byId(request.chain.number) val chain= Chain.byId(request.chain.number)

View File

@@ -1,29 +1,75 @@
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import io.emeraldpay.grpc.Chain
import io.infinitape.etherjar.rpc.RpcCall import io.infinitape.etherjar.rpc.RpcCall
import io.infinitape.etherjar.rpc.RpcClient import io.infinitape.etherjar.rpc.RpcClient
import io.infinitape.etherjar.rpc.RpcException import io.infinitape.etherjar.rpc.RpcException
import io.infinitape.etherjar.rpc.RpcResponseError
import io.infinitape.etherjar.rpc.json.ResponseJson import io.infinitape.etherjar.rpc.json.ResponseJson
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.time.Duration import java.time.Duration
import java.util.*
class EthereumUpstream( class EthereumUpstream(
private val rpcClient: RpcClient, private val rpcClient: RpcClient,
private val objectMapper: ObjectMapper private val objectMapper: ObjectMapper,
private val chain: Chain
) { ) {
private val timeout = Duration.ofSeconds(5) private val timeout = Duration.ofSeconds(5)
private val log = LoggerFactory.getLogger(EthereumUpstream::class.java) 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<Any>): Mono<ByteArray> { fun execute(id: Int, method: String, params: List<Any>): Mono<ByteArray> {
return Mono val result: Mono<Any> = if (hardcodedMethods.contains(method)) {
.fromCompletionStage( Mono.just(method)
.map{ hardcoded(it) }
} else if (allowedMethods.contains(method)) {
Mono.fromCompletionStage(
rpcClient.execute(RpcCall.create(method, Any::class.java, params)) rpcClient.execute(RpcCall.create(method, Any::class.java, params))
) )
.timeout(timeout) .timeout(timeout)
} else {
Mono.error(RpcException(-32601, "Method not allowed or not found"))
}
return result
.doOnError { t -> .doOnError { t ->
log.warn("Upstream error: ${t.message}") 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<String>()
}
throw RpcException(-32601, "Method not found")
}
} }

View File

@@ -22,20 +22,21 @@ class Upstreams(
@PostConstruct @PostConstruct
fun start() { fun start() {
env.getProperty("upstream.ethereum")?.let { env.getProperty("upstream.ethereum")?.let {
chainMapping[Chain.ETHEREUM] = listOf(buildClient(it)) chainMapping[Chain.ETHEREUM] = listOf(buildClient(it, Chain.ETHEREUM))
} }
env.getProperty("upstream.ethereumclassic")?.let { 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 { 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( return EthereumUpstream(
DefaultRpcClient(DefaultRpcTransport(URI(url))), DefaultRpcClient(DefaultRpcTransport(URI(url))),
objectMapper objectMapper,
chain
) )
} }