problem: eth_getBlockByNumber("latest", ...) fails with error

fix: #20
This commit is contained in:
Igor Artamonov
2020-07-02 22:41:34 -04:00
parent fd070d5df4
commit c2bc57d380
9 changed files with 164 additions and 23 deletions

View File

@@ -88,4 +88,7 @@ abstract class AbstractHead : Head {
return head.get()
}
override fun getCurrentHeight(): Long? {
return getCurrent()?.height
}
}

View File

@@ -28,4 +28,8 @@ class EmptyHead : Head {
override fun onBeforeBlock(handler: Runnable) {
}
override fun getCurrentHeight(): Long? {
return null
}
}

View File

@@ -36,4 +36,6 @@ interface Head {
* @see getFlux
*/
fun onBeforeBlock(handler: Runnable)
fun getCurrentHeight(): Long?
}

View File

@@ -117,7 +117,7 @@ open class EthereumMultistream(
}
override fun getRoutedApi(matcher: Selector.Matcher): Mono<Reader<JsonRpcRequest, JsonRpcResponse>> {
return Mono.just(NativeCallRouter(reader, getMethods()))
return Mono.just(NativeCallRouter(reader, getMethods(), getHead()))
}
}

View File

@@ -115,14 +115,14 @@ open class EthereumReader(
)
}
fun blocksByIdAsCont(): Reader<BlockId, BlockContainer> {
open fun blocksByIdAsCont(): Reader<BlockId, BlockContainer> {
return TransformingReader(
blocksById(),
blockAsContainer
)
}
fun blocksByHeightAsCont(): Reader<Long, BlockContainer> {
open fun blocksByHeightAsCont(): Reader<Long, BlockContainer> {
return CompoundReader(
caches.getBlocksByHeight(),
directReader.blockByHeightReader
@@ -139,7 +139,7 @@ open class EthereumReader(
)
}
fun txByHashAsCont(): Reader<TxId, TxContainer> {
open fun txByHashAsCont(): Reader<TxId, TxContainer> {
return CompoundReader(
caches.getTxByHash(),
RekeyingReader(idToTxHash, directReader.txReader)

View File

@@ -15,11 +15,10 @@
*/
package io.emeraldpay.dshackle.upstream.ethereum
import com.fasterxml.jackson.databind.ObjectMapper
import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
@@ -32,7 +31,8 @@ import java.math.BigInteger
class NativeCallRouter(
private val reader: EthereumReader,
private val methods: CallMethods
private val methods: CallMethods,
private val head: Head
) : Reader<JsonRpcRequest, JsonRpcResponse> {
companion object {
@@ -98,12 +98,22 @@ class NativeCallRouter(
}
}
method == "eth_getBlockByNumber" -> {
if (params.size != 2) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 2 parameters")
}
val number: Long
try {
val quantity = HexQuantity.from(params[0].toString()) ?: throw IllegalArgumentException()
getBlockByNumber(params)
}
else -> null
}
}
fun getBlockByNumber(params: List<Any>): Mono<ByteArray>? {
if (params.size != 2) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 2 parameters")
}
val number: Long
try {
val blockRef = params[0].toString()
when {
blockRef.startsWith("0x") -> {
val quantity = HexQuantity.from(blockRef) ?: throw IllegalArgumentException()
number = quantity.value.let {
if (it < BigInteger.valueOf(Long.MAX_VALUE) && it >= BigInteger.ZERO) {
it.toLong()
@@ -111,18 +121,29 @@ class NativeCallRouter(
throw IllegalArgumentException()
}
}
} catch (e: IllegalArgumentException) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be block number")
}
val withTx = params[1].toString().toBoolean()
if (withTx) {
log.warn("Block by number is not implemented")
null
} else {
reader.blocksByHeightAsCont().read(number).map { it.json!! }
blockRef == "latest" -> {
number = head.getCurrentHeight() ?: return null
}
blockRef == "earliest" -> {
number = 0
}
blockRef == "pending" -> {
return null
}
else -> {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Block number is invalid")
}
}
else -> null
} catch (e: IllegalArgumentException) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be block number")
}
val withTx = params[1].toString().toBoolean()
return if (withTx) {
log.warn("Block by number is not implemented")
null
} else {
reader.blocksByHeightAsCont().read(number).map { it.json!! }
}
}
}