problem: proxy doesn't support long ids

fix: #48
This commit is contained in:
Igor Artamonov
2020-08-23 21:31:50 -04:00
parent 64c8cb35f3
commit 54fd5481d6
12 changed files with 57 additions and 39 deletions

View File

@@ -13,7 +13,7 @@ springSecurtyVersion=5.3.2.RELEASE
reactorVersion=3.3.5.RELEASE
nettyVersion=4.1.49.Final
# Our Libs
etherjarVersion=0.10.1
etherjarVersion=0.10.2
# Testing
spockVersion=1.3-groovy-2.5

View File

@@ -26,7 +26,6 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.infinitape.etherjar.rpc.RpcException
import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled
import io.netty.handler.ssl.SslContextBuilder
import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory
import org.springframework.http.HttpHeaders
@@ -37,7 +36,6 @@ import reactor.netty.http.server.HttpServer
import reactor.netty.http.server.HttpServerRequest
import reactor.netty.http.server.HttpServerResponse
import reactor.netty.http.server.HttpServerRoutes
import java.io.File
import java.util.function.BiFunction
/**
@@ -100,8 +98,8 @@ class ProxyServer(
.flatMapMany { call -> execute(chain, call) }
.onErrorResume(RpcException::class.java) { err ->
val id = err.details?.let {
if (it is JsonRpcResponse.Id) it else JsonRpcResponse.IntId(-1)
} ?: JsonRpcResponse.IntId(-1)
if (it is JsonRpcResponse.Id) it else JsonRpcResponse.NumberId(-1)
} ?: JsonRpcResponse.NumberId(-1)
val json = JsonRpcResponse.error(err.code, err.rpcMessage, id)
Mono.just(Global.objectMapper.writeValueAsString(json))

View File

@@ -58,7 +58,7 @@ class QuorumRpcReader(
val defaultResult: Mono<Result> = Mono.just(quorum).flatMap { q ->
if (q.isFailed()) {
Mono.error<Result>(
q.getError()?.asException(JsonRpcResponse.IntId(1))
q.getError()?.asException(JsonRpcResponse.NumberId(1))
?: RpcException(-32000, "Unknown Upstream error")
)
} else {

View File

@@ -211,7 +211,7 @@ open class NativeCall(
companion object {
fun from(t: Throwable): CallError {
return when (t) {
is JsonRpcException -> CallError(t.id.asInt(), t.error.message, t.error)
is JsonRpcException -> CallError(t.id.asNumber().toInt(), t.error.message, t.error)
is RpcException -> CallError(t.code, t.rpcMessage, null)
is CallFailure -> CallError(t.id, t.reason.message ?: "Upstream Error", null)
else -> CallError(1, t.message ?: "Upstream Error", null)

View File

@@ -31,7 +31,7 @@ class JsonRpcError(val code: Int, val message: String, val details: Any?) {
}
fun asException(id: JsonRpcResponse.Id?): JsonRpcException {
return JsonRpcException(id ?: JsonRpcResponse.IntId(-1), this)
return JsonRpcException(id ?: JsonRpcResponse.NumberId(-1), this)
}
override fun equals(other: Any?): Boolean {

View File

@@ -22,7 +22,7 @@ class JsonRpcException(
val error: JsonRpcError
) : Exception(error.message) {
constructor(id: Int, message: String) : this(JsonRpcResponse.IntId(id), JsonRpcError(-32005, message))
constructor(id: Int, message: String) : this(JsonRpcResponse.NumberId(id), JsonRpcError(-32005, message))
companion object {
fun from(err: RpcException): JsonRpcException {
@@ -30,9 +30,9 @@ class JsonRpcException(
if (it is JsonRpcResponse.Id) {
it
} else {
JsonRpcResponse.IntId(-3)
JsonRpcResponse.NumberId(-3)
}
} ?: JsonRpcResponse.IntId(-4)
} ?: JsonRpcResponse.NumberId(-4)
return JsonRpcException(
id, JsonRpcError.from(err)
)

View File

@@ -88,7 +88,7 @@ class JsonRpcHttpClient(
return response.response { header, bytes ->
if (header.status().code() != 200) {
Mono.error(JsonRpcException(JsonRpcResponse.IntId(-2),
Mono.error(JsonRpcException(JsonRpcResponse.NumberId(-2),
JsonRpcError(RpcResponseError.CODE_UPSTREAM_INVALID_RESPONSE, "HTTP Code: ${header.status().code()}"))
)
} else {
@@ -105,7 +105,7 @@ class JsonRpcHttpClient(
.onErrorResume { t ->
val err = when (t) {
is RpcException -> JsonRpcResponse.error(t.code, t.rpcMessage)
is JsonRpcException -> JsonRpcResponse.error(t.error, JsonRpcResponse.IntId(1))
is JsonRpcException -> JsonRpcResponse.error(t.error, JsonRpcResponse.NumberId(1))
else -> JsonRpcResponse.error(1, t.message ?: t.javaClass.name)
}
Mono.just(err)

View File

@@ -26,7 +26,7 @@ class JsonRpcResponse(
val id: Id
) {
constructor(result: ByteArray?, error: JsonRpcError?) : this(result, error, IntId(0))
constructor(result: ByteArray?, error: JsonRpcError?) : this(result, error, NumberId(0))
companion object {
private val NULL_VALUE = "null".toByteArray()
@@ -129,29 +129,31 @@ class JsonRpcResponse(
* JSON RPC wrapper. Makes sure that the id is either Int or String
*/
interface Id {
fun asInt(): Int
fun asNumber(): Long
fun asString(): String
fun isInt(): Boolean
fun isNumber(): Boolean
companion object {
@JvmStatic
fun from(id: Any): Id {
if (id is Int) {
return IntId(id)
return NumberId(id)
}
if (id is Number) {
return IntId(id.toInt())
return NumberId(id.toLong())
}
if (id is String) {
return StringId(id)
}
throw IllegalArgumentException("Id must be Int or String")
throw IllegalArgumentException("Id must be Number or String")
}
}
}
class IntId(val id: Int) : Id {
override fun asInt(): Int {
class NumberId(val id: Long) : Id {
constructor(id: Int) : this(id.toLong())
override fun asNumber(): Long {
return id
}
@@ -159,13 +161,13 @@ class JsonRpcResponse(
throw IllegalStateException("Not string")
}
override fun isInt(): Boolean {
override fun isNumber(): Boolean {
return true
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is IntId) return false
if (other !is NumberId) return false
if (id != other.id) return false
@@ -173,20 +175,20 @@ class JsonRpcResponse(
}
override fun hashCode(): Int {
return id
return id.hashCode()
}
}
class StringId(val id: String) : Id {
override fun asInt(): Int {
throw IllegalStateException("Not int")
override fun asNumber(): Long {
throw IllegalStateException("Not a number")
}
override fun asString(): String {
return id
}
override fun isInt(): Boolean {
override fun isNumber(): Boolean {
return false
}
@@ -209,8 +211,8 @@ class JsonRpcResponse(
override fun serialize(value: JsonRpcResponse, gen: JsonGenerator, serializers: SerializerProvider) {
gen.writeStartObject()
gen.writeStringField("jsonrpc", "2.0")
if (value.id.isInt()) {
gen.writeNumberField("id", value.id.asInt())
if (value.id.isNumber()) {
gen.writeNumberField("id", value.id.asNumber())
} else {
gen.writeStringField("id", value.id.asString())
}

View File

@@ -72,7 +72,7 @@ class ProxyServerSpec extends Specification {
def "Return error on invalid request"() {
setup:
ReadRpcJson read = Mock(ReadRpcJson) {
1 * apply(_) >> { throw new RpcException(-32123, "test", new JsonRpcResponse.IntId(4)) }
1 * apply(_) >> { throw new RpcException(-32123, "test", new JsonRpcResponse.NumberId(4)) }
}
def server = new ProxyServer(
Stub(ProxyConfig),

View File

@@ -16,7 +16,7 @@
*/
package io.emeraldpay.dshackle.proxy
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.infinitape.etherjar.rpc.RpcException
import spock.lang.Specification
@@ -192,7 +192,7 @@ class ReadRpcJsonSpec extends Specification {
def t = thrown(RpcException)
t.code == -32600
t.rpcMessage.toLowerCase() == "jsonrpc version is not set"
t.details == new JsonRpcResponse.IntId(2)
t.details == new JsonRpcResponse.NumberId(2)
}
def "Error if jsonrpc version is invalid"() {
@@ -202,7 +202,7 @@ class ReadRpcJsonSpec extends Specification {
def t = thrown(RpcException)
t.code == -32600
t.rpcMessage.toLowerCase() == "unsupported json rpc version: 3.0"
t.details == new JsonRpcResponse.IntId(2)
t.details == new JsonRpcResponse.NumberId(2)
}
def "Error if method is not set"() {
@@ -212,7 +212,7 @@ class ReadRpcJsonSpec extends Specification {
def t = thrown(RpcException)
t.code == -32600
t.rpcMessage.toLowerCase() == "method is not set"
t.details == new JsonRpcResponse.IntId(2)
t.details == new JsonRpcResponse.NumberId(2)
}
def "Error if params is not array"() {
@@ -222,6 +222,6 @@ class ReadRpcJsonSpec extends Specification {
def t = thrown(RpcException)
t.code == -32600
t.rpcMessage.toLowerCase() == "params must be an array"
t.details == new JsonRpcResponse.IntId(2)
t.details == new JsonRpcResponse.NumberId(2)
}
}

View File

@@ -63,7 +63,7 @@ class JsonRpcResponseSpec extends Specification {
def "Serialize int id and null result"() {
setup:
def json = new JsonRpcResponse("null".bytes, null, new JsonRpcResponse.IntId(1))
def json = new JsonRpcResponse("null".bytes, null, new JsonRpcResponse.NumberId(1))
when:
def act = objectMapper.writeValueAsString(json)
then:
@@ -72,7 +72,7 @@ class JsonRpcResponseSpec extends Specification {
def "Serialize int id and string result"() {
setup:
def json = new JsonRpcResponse('"Hello World"'.bytes, null, new JsonRpcResponse.IntId(10))
def json = new JsonRpcResponse('"Hello World"'.bytes, null, new JsonRpcResponse.NumberId(10))
when:
def act = objectMapper.writeValueAsString(json)
then:
@@ -81,7 +81,7 @@ class JsonRpcResponseSpec extends Specification {
def "Serialize int id and object result"() {
setup:
def json = new JsonRpcResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new JsonRpcResponse.IntId(101))
def json = new JsonRpcResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new JsonRpcResponse.NumberId(101))
when:
def act = objectMapper.writeValueAsString(json)
then:
@@ -90,7 +90,7 @@ class JsonRpcResponseSpec extends Specification {
def "Serialize int id and error"() {
setup:
def json = new JsonRpcResponse(null, new JsonRpcError(-32041, "Oooops"), new JsonRpcResponse.IntId(101))
def json = new JsonRpcResponse(null, new JsonRpcError(-32041, "Oooops"), new JsonRpcResponse.NumberId(101))
when:
def act = objectMapper.writeValueAsString(json)
then:

View File

@@ -0,0 +1,18 @@
package io.emeraldpay.dshackle.testing.trial.proxy
import io.emeraldpay.dshackle.testing.trial.ProxyClient
import spock.lang.Specification
class MetamaskCallSpec extends Specification {
def client = ProxyClient.forPrefix("eth")
def "use long id"() {
when:
def act = client.execute(1057264140543346, "net_version", [])
then:
act.id == 1057264140543346
act.result != null
act.error == null
}
}