diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index 29e690f5..912f7c64 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -27,7 +27,6 @@ import io.emeraldpay.dshackle.quorum.CallQuorum import io.emeraldpay.dshackle.quorum.NotLaggingQuorum import io.emeraldpay.dshackle.quorum.QuorumReaderFactory import io.emeraldpay.dshackle.quorum.QuorumRpcReader -import io.emeraldpay.dshackle.startup.ConfiguredUpstreams import io.emeraldpay.dshackle.startup.UpstreamChangeEvent import io.emeraldpay.dshackle.upstream.* import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods @@ -56,7 +55,6 @@ import java.util.concurrent.atomic.AtomicInteger @Service open class NativeCall( private val multistreamHolder: MultistreamHolder, - private val configuredUpstreams: ConfiguredUpstreams, private val signer: ResponseSigner ) { @@ -76,7 +74,7 @@ open class NativeCall( @EventListener fun onUpstreamChangeEvent(event: UpstreamChangeEvent) { casting[BlockchainType.from(event.chain)]?.let { cast -> - multistreamHolder.getUpstream(event.chain)?.let { up -> + multistreamHolder.getUpstream(event.chain).let { up -> val reader = up.cast(cast).getReader() ethereumCallSelectors.putIfAbsent(event.chain, EthereumCallSelector(reader.heightByHash())) } @@ -98,6 +96,7 @@ open class NativeCall( .doOnError { e -> log.warn("Error during native call: ${e.message}") } } else { val error = it.getError() + Mono.just( CallResult(error.id, 0, null, error, null, null) ) @@ -274,6 +273,7 @@ open class NativeCall( api.read(JsonRpcRequest(ctx.payload.method, ctx.payload.params, ctx.nonce, ctx.forwardedSelector)) .flatMap(JsonRpcResponse::requireResult) .map { + validateResult(it, "local", ctx) if (ctx.nonce != null) { CallResult.ok(ctx.id, ctx.nonce, it, signer.sign(ctx.nonce, it, ctx.upstream.getId()), ctx.upstream.getId()) } else { @@ -299,11 +299,13 @@ open class NativeCall( } else { AtomicInteger(-1) } + return reader .read(JsonRpcRequest(ctx.payload.method, ctx.payload.params, ctx.nonce, ctx.forwardedSelector)) .map { val bytes = ctx.resultDecorator.processResult(it) - CallResult(ctx.id, ctx.nonce, bytes, null, it.signature, ctx.upstream.getId()) + validateResult(bytes, "remote", ctx) + CallResult.ok(ctx.id, ctx.nonce, bytes, it.signature, ctx.upstream.getId()) } .onErrorResume { t -> Mono.just(CallResult.fail(ctx.id, ctx.nonce, t)) @@ -322,6 +324,11 @@ open class NativeCall( ) } + private fun validateResult(bytes: ByteArray, origin: String, ctx: ValidCallContext) { + if (bytes.isEmpty()) + log.warn("Empty result from origin $origin, method ${ctx.payload.method}, params ${ctx.payload.params}") + } + private fun errorMessage(attempts: Int, method: String): String = when (attempts) { -1 -> "No response or no available upstream for $method" diff --git a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy index e66daa89..8a45dc30 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy @@ -54,17 +54,14 @@ class NativeCallSpec extends Specification { ObjectMapper objectMapper = Global.objectMapper - def nativeCall(MultistreamHolder upstreams = null, ResponseSigner signer = null, ConfiguredUpstreams configuredUpstreams = null) { + def nativeCall(MultistreamHolder upstreams = null, ResponseSigner signer = null) { if (upstreams == null) { upstreams = Stub(MultistreamHolder) } if (signer == null) { signer = Stub(ResponseSigner) } - if (configuredUpstreams == null) { - configuredUpstreams = Stub(ConfiguredUpstreams) - } - new NativeCall(upstreams, configuredUpstreams, signer) + new NativeCall(upstreams, signer) } def "Tries router first"() {