From 6cc0e186929f52b176766d2f238f2b65ff52bbef Mon Sep 17 00:00:00 2001 From: a10zn8 Date: Tue, 27 Feb 2024 17:35:03 +0300 Subject: [PATCH] support object params --- .../io/emeraldpay/dshackle/rpc/NativeCall.kt | 30 +++-- .../upstream/bitcoin/BitcoinReader.kt | 7 +- .../upstream/bitcoin/BitcoinRpcHead.kt | 5 +- .../bitcoin/BitcoinUpstreamValidator.kt | 3 +- .../upstream/bitcoin/BitcoinZMQHead.kt | 3 +- .../upstream/bitcoin/CachingMempoolData.kt | 3 +- .../upstream/bitcoin/LocalCallRouter.kt | 23 ++-- .../upstream/bitcoin/RpcUnspentReader.kt | 3 +- .../EthereumArchiveBlockNumberReader.kt | 3 +- .../ethereum/EthereumChainSpecific.kt | 7 +- .../upstream/ethereum/EthereumDirectReader.kt | 13 ++- .../upstream/ethereum/EthereumLocalReader.kt | 109 ++++++++++-------- .../EthereumLowerBoundBlockDetector.kt | 3 +- .../ethereum/EthereumUpstreamValidator.kt | 13 ++- .../upstream/ethereum/WsSubscriptionsImpl.kt | 4 +- .../subscribe/EthereumLabelsDetector.kt | 5 +- .../subscribe/WebsocketPendingTxes.kt | 3 +- .../generic/GenericIngressSubscription.kt | 3 +- .../upstream/grpc/BitcoinGrpcUpstream.kt | 3 +- .../upstream/near/NearChainSpecific.kt | 8 +- .../near/NearLowerBoundBlockDetector.kt | 3 +- .../polkadot/PolkadotChainSpecific.kt | 9 +- .../PolkadotLowerBoundBlockDetector.kt | 5 +- .../dshackle/upstream/rpcclient/CallParams.kt | 11 ++ .../upstream/rpcclient/JsonRpcGrpcClient.kt | 11 +- .../upstream/rpcclient/JsonRpcRequest.kt | 18 ++- .../upstream/solana/SolanaChainSpecific.kt | 13 ++- .../solana/SolanaLowerBoundBlockDetector.kt | 5 +- .../starknet/StarknetChainSpecific.kt | 5 +- .../quorum/QuorumRpcReaderSpec.groovy | 35 +++--- .../reader/BroadcastReaderSpec.groovy | 31 ++--- .../dshackle/rpc/NativeCallSpec.groovy | 37 +++--- .../dshackle/test/ApiReaderMock.groovy | 2 +- .../bitcoin/BitcoinRpcHeadSpec.groovy | 7 +- .../bitcoin/RpcUnspentReaderSpec.groovy | 5 +- .../ethereum/EthereumCachingReaderSpec.groovy | 31 ++--- .../EthereumLabelsDetectorSpec.groovy | 9 +- .../ethereum/EthereumLocalReaderSpec.groovy | 5 +- .../EthereumUpstreamValidatorSpec.groovy | 62 +++++----- .../ethereum/GenericWsHeadSpec.groovy | 7 +- .../ethereum/WsConnectionImplRealSpec.groovy | 11 +- .../ethereum/WsConnectionImplSpec.groovy | 7 +- .../ethereum/WsSubscriptionsImplSpec.groovy | 9 +- .../subscribe/WebsocketPendingTxesSpec.groovy | 3 +- .../rpcclient/JsonRpcGrpcClientSpec.groovy | 5 +- .../rpcclient/JsonRpcHttpClientSpec.groovy | 7 +- .../rpcclient/JsonRpcRequestSpec.groovy | 11 +- .../rpcclient/JsonRpcWsClientSpec.groovy | 3 +- .../RecursiveLowerBoundBlockDetectorTest.kt | 13 ++- .../SolanaLowerBoundBlockDetectorTest.kt | 5 +- 50 files changed, 360 insertions(+), 276 deletions(-) create mode 100644 src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/CallParams.kt diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index 967e9566..6ad6941e 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -43,9 +43,12 @@ import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError +import io.emeraldpay.dshackle.upstream.rpcclient.CallParams import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams +import io.emeraldpay.dshackle.upstream.rpcclient.ObjectParams import io.emeraldpay.dshackle.upstream.rpcclient.stream.Chunk import io.emeraldpay.dshackle.upstream.signature.ResponseSigner import io.micrometer.core.instrument.Metrics @@ -472,12 +475,16 @@ open class NativeCall( } @Suppress("UNCHECKED_CAST") - private fun extractParams(jsonParams: String): List { + private fun extractParams(jsonParams: String): CallParams { if (StringUtils.isEmpty(jsonParams) || jsonParams == "null") { - return emptyList() + return ListParams() + } + if (jsonParams.trimStart().startsWith("{")) { + val req = objectMapper.readValue(jsonParams, Map::class.java) + return ObjectParams(req as Map) } val req = objectMapper.readValue(jsonParams, List::class.java) - return req as List + return ListParams(req as List) } abstract class CallContext( @@ -517,18 +524,21 @@ open class NativeCall( } interface RequestDecorator { - fun processRequest(request: List): List + fun processRequest(request: CallParams): CallParams } open class NoneRequestDecorator : RequestDecorator { - override fun processRequest(request: List): List = request + override fun processRequest(request: CallParams): CallParams = request } open class WithFilterIdDecorator : RequestDecorator { - override fun processRequest(request: List): List { - val filterId = request.first().toString() - val sanitized = filterId.substring(0, filterId.lastIndex - 1) - return listOf(sanitized) + override fun processRequest(request: CallParams): CallParams { + if (request is ListParams) { + val filterId = request.list.first().toString() + val sanitized = filterId.substring(0, filterId.lastIndex - 1) + return ListParams(listOf(sanitized)) + } + return request } } @@ -696,5 +706,5 @@ open class NativeCall( } class RawCallDetails(val method: String, val params: String) - class ParsedCallDetails(val method: String, val params: List) + class ParsedCallDetails(val method: String, val params: CallParams) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinReader.kt index d076ea9b..f8bf12a4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinReader.kt @@ -24,6 +24,7 @@ import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.bitcoinj.core.Address import org.slf4j.LoggerFactory import reactor.core.publisher.Mono @@ -55,16 +56,16 @@ open class BitcoinReader( } open fun getBlock(hash: String): Mono> { - return castedRead(JsonRpcRequest("getblock", listOf(hash)), Map::class.java).cast() + return castedRead(JsonRpcRequest("getblock", ListParams(hash)), Map::class.java).cast() } open fun getBlock(height: Long): Mono> { - return castedRead(JsonRpcRequest("getblockhash", listOf(height)), String::class.java) + return castedRead(JsonRpcRequest("getblockhash", ListParams(height)), String::class.java) .flatMap(this@BitcoinReader::getBlock) } open fun getTx(txid: String): Mono> { - return castedRead(JsonRpcRequest("getrawtransaction", listOf(txid, true)), Map::class.java).cast() + return castedRead(JsonRpcRequest("getrawtransaction", ListParams(txid, true)), Map::class.java).cast() } open fun listUnspent(address: Address): Mono> { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHead.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHead.kt index b3944ede..fa502ce5 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHead.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHead.kt @@ -23,6 +23,7 @@ import io.emeraldpay.dshackle.upstream.Lifecycle import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.springframework.scheduling.concurrent.CustomizableThreadFactory import reactor.core.Disposable import reactor.core.publisher.Flux @@ -59,13 +60,13 @@ class BitcoinRpcHead( val base = Flux.interval(interval) .publishOn(scheduler) .flatMap { - api.read(JsonRpcRequest("getbestblockhash", emptyList())) + api.read(JsonRpcRequest("getbestblockhash", ListParams())) .flatMap(JsonRpcResponse::requireStringResult) .timeout(Defaults.timeout, Mono.error(Exception("Best block hash is not received"))) } .distinctUntilChanged() .flatMap { hash -> - api.read(JsonRpcRequest("getblock", listOf(hash))) + api.read(JsonRpcRequest("getblock", ListParams(hash))) .flatMap(JsonRpcResponse::requireResult) .map(extractBlock::extract) .timeout(Defaults.timeout, Mono.error(Exception("Block data is not received"))) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinUpstreamValidator.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinUpstreamValidator.kt index e572bfd3..84cdc120 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinUpstreamValidator.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinUpstreamValidator.kt @@ -20,6 +20,7 @@ import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import org.springframework.scheduling.concurrent.CustomizableThreadFactory import reactor.core.publisher.Flux @@ -40,7 +41,7 @@ class BitcoinUpstreamValidator( } fun validate(): Mono { - return api.read(JsonRpcRequest("getconnectioncount", emptyList())) + return api.read(JsonRpcRequest("getconnectioncount", ListParams())) .flatMap(JsonRpcResponse::requireResult) .map { Integer.parseInt(String(it)) } .map { count -> diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinZMQHead.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinZMQHead.kt index 9451eb61..46843323 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinZMQHead.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinZMQHead.kt @@ -9,6 +9,7 @@ import io.emeraldpay.dshackle.upstream.Lifecycle import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.apache.commons.codec.binary.Hex import reactor.core.Disposable import reactor.core.publisher.Flux @@ -32,7 +33,7 @@ class BitcoinZMQHead( Hex.encodeHexString(it) } .flatMap { hash -> - api.read(JsonRpcRequest("getblock", listOf(hash))) + api.read(JsonRpcRequest("getblock", ListParams(hash))) .switchIfEmpty(Mono.error(IllegalStateException("Block $hash is not available on upstream"))) .retryWhen(Retry.backoff(5, Duration.ofMillis(100))) .switchIfEmpty(Mono.fromCallable { log.warn("Block $hash is not available on upstream") }.then(Mono.empty())) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/CachingMempoolData.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/CachingMempoolData.kt index acda2cbc..0d709176 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/CachingMempoolData.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/CachingMempoolData.kt @@ -22,6 +22,7 @@ import io.emeraldpay.dshackle.upstream.Lifecycle import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import reactor.core.Disposable import reactor.core.publisher.Mono @@ -65,7 +66,7 @@ open class CachingMempoolData( @Suppress("UNCHECKED_CAST") fun fetchFromUpstream(): Mono> { return upstreams.getDirectApi(Selector.empty).flatMap { api -> - api.read(JsonRpcRequest("getrawmempool", emptyList())) + api.read(JsonRpcRequest("getrawmempool", ListParams())) .flatMap(JsonRpcResponse::requireResult) .map { objectMapper.readValue(it, List::class.java) as List } } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt index 829f03ba..2f78f987 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/LocalCallRouter.kt @@ -25,6 +25,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.bitcoinj.core.Address import org.slf4j.LoggerFactory import reactor.core.publisher.Mono @@ -63,16 +64,18 @@ class LocalCallRouter( * */ fun processUnspentRequest(key: JsonRpcRequest): Mono { - if (key.params.size < 3) { - return Mono.error(SilentException("Invalid call to unspent. Address is missing")) - } - val addresses = key.params[2] - if (addresses is List<*> && addresses.size > 0) { - val address = addresses[0].toString().let { Address.fromString(null, it) } - return reader.listUnspent(address).map { - val rpc = it.map(convertUnspent(address)) - val json = Global.objectMapper.writeValueAsBytes(rpc) - JsonRpcResponse.ok(json, JsonRpcResponse.NumberId(key.id)) + if (key.params is ListParams) { + if (key.params.list.size < 3) { + return Mono.error(SilentException("Invalid call to unspent. Address is missing")) + } + val addresses = key.params.list[2] + if (addresses is List<*> && addresses.size > 0) { + val address = addresses[0].toString().let { Address.fromString(null, it) } + return reader.listUnspent(address).map { + val rpc = it.map(convertUnspent(address)) + val json = Global.objectMapper.writeValueAsBytes(rpc) + JsonRpcResponse.ok(json, JsonRpcResponse.NumberId(key.id)) + } } } return Mono.error(SilentException("Invalid call to unspent")) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReader.kt index 19db031e..fc57c2d9 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReader.kt @@ -23,6 +23,7 @@ import io.emeraldpay.dshackle.upstream.bitcoin.data.RpcUnspent import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.bitcoinj.core.Address import org.slf4j.LoggerFactory import reactor.core.publisher.Mono @@ -50,7 +51,7 @@ class RpcUnspentReader( // val address = key.toString() return upstreams.getDirectApi(selector).flatMap { api -> - api.read(JsonRpcRequest("listunspent", listOf(1, 9999999, listOf(address)))) + api.read(JsonRpcRequest("listunspent", ListParams(1, 9999999, listOf(address)))) .flatMap(JsonRpcResponse::requireResult) .map { Global.objectMapper.readerFor(RpcUnspent::class.java).readValues(it).readAll() diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumArchiveBlockNumberReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumArchiveBlockNumberReader.kt index 201760ad..59a09ed3 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumArchiveBlockNumberReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumArchiveBlockNumberReader.kt @@ -5,6 +5,7 @@ import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.upstream.ethereum.hex.HexQuantity import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Mono import kotlin.math.max @@ -17,7 +18,7 @@ class EthereumArchiveBlockNumberReader( ) { fun readArchiveBlock(): Mono = - reader.read(JsonRpcRequest("eth_blockNumber", listOf())) + reader.read(JsonRpcRequest("eth_blockNumber", ListParams())) .flatMap(JsonRpcResponse::requireResult) .map { HexQuantity diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumChainSpecific.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumChainSpecific.kt index afcc1e3e..4df8c83e 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumChainSpecific.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumChainSpecific.kt @@ -28,6 +28,7 @@ import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific import io.emeraldpay.dshackle.upstream.generic.CachingReaderBuilder import io.emeraldpay.dshackle.upstream.generic.GenericUpstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.springframework.cloud.sleuth.Tracer import reactor.core.publisher.Mono import reactor.core.scheduler.Scheduler @@ -41,10 +42,10 @@ object EthereumChainSpecific : AbstractPollChainSpecific() { return parseBlock(data, upstreamId) } - override fun latestBlockRequest() = JsonRpcRequest("eth_getBlockByNumber", listOf("latest", false)) - override fun listenNewHeadsRequest(): JsonRpcRequest = JsonRpcRequest("eth_subscribe", listOf("newHeads")) + override fun latestBlockRequest() = JsonRpcRequest("eth_getBlockByNumber", ListParams("latest", false)) + override fun listenNewHeadsRequest(): JsonRpcRequest = JsonRpcRequest("eth_subscribe", ListParams("newHeads")) override fun unsubscribeNewHeadsRequest(subId: String): JsonRpcRequest = - JsonRpcRequest("eth_unsubscribe", listOf(subId)) + JsonRpcRequest("eth_unsubscribe", ListParams(subId)) override fun localReaderBuilder( cachingReader: CachingReader, diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumDirectReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumDirectReader.kt index aac950d3..f5f186f2 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumDirectReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumDirectReader.kt @@ -31,6 +31,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.apache.commons.collections4.Factory import org.apache.commons.lang3.exception.ExceptionUtils import org.slf4j.LoggerFactory @@ -68,20 +69,20 @@ class EthereumDirectReader( init { blockReader = object : Reader> { override fun read(key: BlockHash): Mono> { - val request = JsonRpcRequest("eth_getBlockByHash", listOf(key.toHex(), false)) + val request = JsonRpcRequest("eth_getBlockByHash", ListParams(key.toHex(), false)) return readBlock(request, key.toHex()) } } blockByHeightReader = object : Reader> { override fun read(key: Long): Mono> { val heightMatcher = Selector.HeightMatcher(key) - val request = JsonRpcRequest("eth_getBlockByNumber", listOf(HexQuantity.from(key).toHex(), false)) + val request = JsonRpcRequest("eth_getBlockByNumber", ListParams(HexQuantity.from(key).toHex(), false)) return readBlock(request, key.toString(), heightMatcher) } } txReader = object : Reader> { override fun read(key: TransactionId): Mono> { - val request = JsonRpcRequest("eth_getTransactionByHash", listOf(key.toHex())) + val request = JsonRpcRequest("eth_getTransactionByHash", ListParams(key.toHex())) return readWithQuorum(request) // retries were removed because we use NotNullQuorum which handle errors too .timeout(Duration.ofSeconds(5), Mono.error(TimeoutException("Tx not read $key"))) .flatMap { result -> @@ -106,7 +107,7 @@ class EthereumDirectReader( balanceReader = object : Reader> { override fun read(key: Address): Mono> { val height = up.getHead().getCurrentHeight()?.let { HexQuantity.from(it).toHex() } ?: "latest" - val request = JsonRpcRequest("eth_getBalance", listOf(key.toHex(), height)) + val request = JsonRpcRequest("eth_getBalance", ListParams(key.toHex(), height)) return readWithQuorum(request) .timeout(Defaults.timeoutInternal, Mono.error(TimeoutException("Balance not read $key"))) .map { @@ -130,7 +131,7 @@ class EthereumDirectReader( receiptReader = object : Reader> { override fun read(key: TransactionId): Mono> { - val request = JsonRpcRequest("eth_getTransactionReceipt", listOf(key.toHex())) + val request = JsonRpcRequest("eth_getTransactionReceipt", ListParams(key.toHex())) return readWithQuorum(request) .timeout(Duration.ofSeconds(5), Mono.error(TimeoutException("Receipt not read $key"))) .flatMap { result -> @@ -163,7 +164,7 @@ class EthereumDirectReader( override fun read(key: BlockId): Mono>> { val request = JsonRpcRequest( "eth_getLogs", - listOf( + ListParams( mapOf( "blockHash" to key.toHexWithPrefix(), ), diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReader.kt index a2b8a10b..dd965b35 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReader.kt @@ -27,6 +27,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Mono import reactor.kotlin.core.publisher.switchIfEmpty import java.math.BigInteger @@ -73,60 +74,68 @@ class EthereumLocalReader( fun commonRequests(key: JsonRpcRequest): Mono>? { val method = key.method val params = key.params - return when { - method == "eth_getTransactionByHash" -> { - if (params.size != 1) { - throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 1 parameter") + if (params is ListParams) { + return when { + method == "eth_getTransactionByHash" -> { + if (params.list.size != 1) { + throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 1 parameter") + } + val hash: TxId + try { + hash = TxId.from(params.list[0].toString()) + } catch (e: IllegalArgumentException) { + throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be transaction id") + } + reader.txByHashAsCont() + .read(hash) + .map { it.data.json!! to it.upstreamId } } - val hash: TxId - try { - hash = TxId.from(params[0].toString()) - } catch (e: IllegalArgumentException) { - throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be transaction id") + + method == "eth_getBlockByHash" -> { + if (params.list.size != 2) { + throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 2 parameters") + } + val hash: BlockId + try { + hash = BlockId.from(params.list[0].toString()) + } catch (e: IllegalArgumentException) { + throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be block hash") + } + val withTx = params.list[1].toString().toBoolean() + if (withTx) { + null + } else { + reader.blocksByIdAsCont().read(hash).map { it.data.json!! to it.upstreamId } + } } - reader.txByHashAsCont() - .read(hash) - .map { it.data.json!! to it.upstreamId } + + method == "eth_getBlockByNumber" -> { + getBlockByNumber(params.list) + } + + method == "eth_getTransactionReceipt" -> { + if (params.list.size != 1) { + throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 1 parameter") + } + val hash: TxId + try { + hash = TxId.from(params.list[0].toString()) + } catch (e: IllegalArgumentException) { + throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be transaction id") + } + reader.receipts() + .read(hash) + .map { it.data to it.upstreamId } + } + + method == "drpc_getLogsEstimate" -> { + getLogsEstimate(params.list) + } + + else -> null } - method == "eth_getBlockByHash" -> { - if (params.size != 2) { - throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 2 parameters") - } - val hash: BlockId - try { - hash = BlockId.from(params[0].toString()) - } catch (e: IllegalArgumentException) { - throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be block hash") - } - val withTx = params[1].toString().toBoolean() - if (withTx) { - null - } else { - reader.blocksByIdAsCont().read(hash).map { it.data.json!! to it.upstreamId } - } - } - method == "eth_getBlockByNumber" -> { - getBlockByNumber(params) - } - method == "eth_getTransactionReceipt" -> { - if (params.size != 1) { - throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 1 parameter") - } - val hash: TxId - try { - hash = TxId.from(params[0].toString()) - } catch (e: IllegalArgumentException) { - throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "[0] must be transaction id") - } - reader.receipts() - .read(hash) - .map { it.data to it.upstreamId } - } - method == "drpc_getLogsEstimate" -> { - getLogsEstimate(params) - } - else -> null } + return null } fun getBlockByNumber(params: List): Mono>? { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLowerBoundBlockDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLowerBoundBlockDetector.kt index feb82009..fb938183 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLowerBoundBlockDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLowerBoundBlockDetector.kt @@ -5,6 +5,7 @@ import io.emeraldpay.dshackle.upstream.RecursiveLowerBoundBlockDetector import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.toHex import reactor.core.publisher.Mono @@ -46,7 +47,7 @@ class EthereumLowerBoundBlockDetector( return upstream.getIngressReader().read( JsonRpcRequest( "eth_getBalance", - listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", blockNumber.toHex()), + ListParams("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", blockNumber.toHex()), ), ) .retryWhen(retrySpec(nonRetryableErrors)) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidator.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidator.kt index fbb7c29a..68310a80 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidator.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidator.kt @@ -32,6 +32,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.json.SyncingJson import io.emeraldpay.dshackle.upstream.ethereum.json.TransactionCallJson import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import org.springframework.scheduling.concurrent.CustomizableThreadFactory import reactor.core.publisher.Mono @@ -79,7 +80,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor( return Mono.just(UpstreamAvailability.OK) } return upstream.getIngressReader() - .read(JsonRpcRequest("eth_syncing", listOf())) + .read(JsonRpcRequest("eth_syncing", ListParams())) .flatMap(JsonRpcResponse::requireResult) .map { objectMapper.readValue(it, SyncingJson::class.java) } .timeout( @@ -106,7 +107,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor( } return upstream .getIngressReader() - .read(JsonRpcRequest("net_peerCount", listOf())) + .read(JsonRpcRequest("net_peerCount", ListParams())) .flatMap(JsonRpcResponse::requireStringResult) .map(Integer::decode) .timeout( @@ -179,7 +180,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor( .read( JsonRpcRequest( "eth_call", - listOf( + ListParams( TransactionCallJson( Address.from(config.callLimitContract), // calling contract with param 200_000, meaning it will generate 200k symbols or response @@ -223,7 +224,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor( .readArchiveBlock() .flatMap { upstream.getIngressReader() - .read(JsonRpcRequest("eth_getBlockByNumber", listOf(it, false))) + .read(JsonRpcRequest("eth_getBlockByNumber", ListParams(it, false))) .flatMap(JsonRpcResponse::requireResult) } .retryRandomBackoff(3, Duration.ofMillis(100), Duration.ofMillis(500)) { ctx -> @@ -249,7 +250,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor( private fun chainId(): Mono { return upstream.getIngressReader() - .read(JsonRpcRequest("eth_chainId", emptyList())) + .read(JsonRpcRequest("eth_chainId", ListParams())) .retryRandomBackoff(3, Duration.ofMillis(100), Duration.ofMillis(500)) { ctx -> log.warn( "error during chainId retrieving for ${upstream.getId()}, iteration ${ctx.iteration()}, " + @@ -262,7 +263,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor( private fun netVersion(): Mono { return upstream.getIngressReader() - .read(JsonRpcRequest("net_version", emptyList())) + .read(JsonRpcRequest("net_version", ListParams())) .retryRandomBackoff(3, Duration.ofMillis(100), Duration.ofMillis(500)) { ctx -> log.warn( "error during netVersion retrieving for ${upstream.getId()}, iteration ${ctx.iteration()}, " + diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImpl.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImpl.kt index 7a79898a..0d0f50ee 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImpl.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImpl.kt @@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.ethereum import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -54,7 +55,8 @@ class WsSubscriptionsImpl( } override fun unsubscribe(request: JsonRpcRequest): Mono { - if (request.params.isEmpty() || request.params.contains("")) { + if (request.params is ListParams && (request.params.list.isEmpty() || request.params.list.contains("")) + ) { return Mono.empty() } return wsPool.getConnection() diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt index f0e885c3..7a97a5d0 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/EthereumLabelsDetector.kt @@ -9,6 +9,7 @@ import io.emeraldpay.dshackle.upstream.LabelsDetector import io.emeraldpay.dshackle.upstream.ethereum.EthereumArchiveBlockNumberReader import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -32,7 +33,7 @@ class EthereumLabelsDetector( private fun detectNodeType(): Flux?> { return reader - .read(JsonRpcRequest("web3_clientVersion", listOf())) + .read(JsonRpcRequest("web3_clientVersion", ListParams())) .flatMap(JsonRpcResponse::requireResult) .map { objectMapper.readValue(it) } .flatMapMany { node -> @@ -64,7 +65,7 @@ class EthereumLabelsDetector( return reader.read( JsonRpcRequest( "eth_getBalance", - listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", blockNumber), + ListParams("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", blockNumber), ), ).flatMap(JsonRpcResponse::requireResult) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxes.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxes.kt index 82687859..09ecda74 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxes.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxes.kt @@ -20,6 +20,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.EthereumEgressSubscription import io.emeraldpay.dshackle.upstream.ethereum.WsSubscriptions import io.emeraldpay.dshackle.upstream.ethereum.domain.TransactionId import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -34,7 +35,7 @@ class WebsocketPendingTxes( } override fun createConnection(): Flux { - return wsSubscriptions.subscribe(JsonRpcRequest("eth_subscribe", listOf(EthereumEgressSubscription.METHOD_PENDING_TXES))) + return wsSubscriptions.subscribe(JsonRpcRequest("eth_subscribe", ListParams(EthereumEgressSubscription.METHOD_PENDING_TXES))) .data .timeout(Duration.ofSeconds(60), Mono.empty()) .map { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/GenericIngressSubscription.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/GenericIngressSubscription.kt index 6b993746..eb2f9109 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/GenericIngressSubscription.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/generic/GenericIngressSubscription.kt @@ -5,6 +5,7 @@ import io.emeraldpay.dshackle.upstream.SubscriptionConnect import io.emeraldpay.dshackle.upstream.ethereum.WsSubscriptions import io.emeraldpay.dshackle.upstream.generic.subscribe.GenericPersistentConnect import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Flux import reactor.core.publisher.Mono import java.time.Duration @@ -37,7 +38,7 @@ class GenericSubscriptionConnect( @Suppress("UNCHECKED_CAST") override fun createConnection(): Flux { - return conn.subscribe(JsonRpcRequest(topic, getParams(params))) + return conn.subscribe(JsonRpcRequest(topic, ListParams(getParams(params)))) .data .timeout(Duration.ofSeconds(60), Mono.empty()) .onErrorResume { Mono.empty() } as Flux diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/BitcoinGrpcUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/BitcoinGrpcUpstream.kt index a13bbbff..8a0e7daf 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/BitcoinGrpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/BitcoinGrpcUpstream.kt @@ -39,6 +39,7 @@ import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.reactivestreams.Publisher import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -93,7 +94,7 @@ class BitcoinGrpcUpstream( private val reloadBlock: Function> = Function { existingBlock -> // head comes without transaction data // need to download transactions for the block - defaultReader.read(JsonRpcRequest("getblock", listOf(existingBlock.hash.toHex()))) + defaultReader.read(JsonRpcRequest("getblock", ListParams(existingBlock.hash.toHex()))) .flatMap(JsonRpcResponse::requireResult) .map(extractBlock::extract) .timeout(timeout, Mono.error(TimeoutException("Timeout from upstream"))) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearChainSpecific.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearChainSpecific.kt index 14279a11..b6fc82b9 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearChainSpecific.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearChainSpecific.kt @@ -16,6 +16,8 @@ import io.emeraldpay.dshackle.upstream.UpstreamValidator import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams +import io.emeraldpay.dshackle.upstream.rpcclient.ObjectParams import java.math.BigInteger import java.time.Instant import java.util.concurrent.TimeUnit @@ -60,7 +62,7 @@ object NearChainSpecific : AbstractPollChainSpecific() { upstream, options, SingleCallValidator( - JsonRpcRequest("status", listOf()), + JsonRpcRequest("status", ListParams()), ) { data -> validate(data) }, @@ -80,8 +82,8 @@ object NearChainSpecific : AbstractPollChainSpecific() { } } - override fun latestBlockRequest(): JsonRpcRequest = - JsonRpcRequest("block", mapOf("finality" to "optimistic")) + override fun latestBlockRequest(): JsonRpcRequest = // {...} + JsonRpcRequest("block", ObjectParams("finality" to "optimistic")) } @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearLowerBoundBlockDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearLowerBoundBlockDetector.kt index 13a0fda8..a7d162d7 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearLowerBoundBlockDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/near/NearLowerBoundBlockDetector.kt @@ -5,6 +5,7 @@ import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.upstream.LowerBoundBlockDetector import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Mono class NearLowerBoundBlockDetector( @@ -13,7 +14,7 @@ class NearLowerBoundBlockDetector( ) : LowerBoundBlockDetector(chain, upstream) { override fun lowerBlockDetect(): Mono { - return upstream.getIngressReader().read(JsonRpcRequest("status", listOf())).map { + return upstream.getIngressReader().read(JsonRpcRequest("status", ListParams())).map { val resp = Global.objectMapper.readValue(it.getResult(), NearStatus::class.java) LowerBlockData(resp.syncInfo.earliestHeight, null, resp.syncInfo.earliestBlockTime.toEpochMilli()) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotChainSpecific.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotChainSpecific.kt index 4edf880c..63a407b6 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotChainSpecific.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotChainSpecific.kt @@ -29,6 +29,7 @@ import io.emeraldpay.dshackle.upstream.generic.GenericIngressSubscription import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator import io.emeraldpay.dshackle.upstream.generic.LocalReader import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import reactor.core.publisher.Mono import reactor.core.scheduler.Scheduler @@ -66,13 +67,13 @@ object PolkadotChainSpecific : AbstractPollChainSpecific() { } override fun latestBlockRequest(): JsonRpcRequest = - JsonRpcRequest("chain_getBlock", listOf()) + JsonRpcRequest("chain_getBlock", ListParams()) override fun listenNewHeadsRequest(): JsonRpcRequest = - JsonRpcRequest("chain_subscribeNewHeads", listOf()) + JsonRpcRequest("chain_subscribeNewHeads", ListParams()) override fun unsubscribeNewHeadsRequest(subId: String): JsonRpcRequest = - JsonRpcRequest("chain_unsubscribeNewHeads", listOf(subId)) + JsonRpcRequest("chain_unsubscribeNewHeads", ListParams(subId)) override fun localReaderBuilder( cachingReader: CachingReader, @@ -97,7 +98,7 @@ object PolkadotChainSpecific : AbstractPollChainSpecific() { upstream, options, SingleCallValidator( - JsonRpcRequest("system_health", listOf()), + JsonRpcRequest("system_health", ListParams()), ) { data -> validate(data, options.minPeers, upstream.getId()) }, diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotLowerBoundBlockDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotLowerBoundBlockDetector.kt index 04b0fad1..de919cac 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotLowerBoundBlockDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/polkadot/PolkadotLowerBoundBlockDetector.kt @@ -5,6 +5,7 @@ import io.emeraldpay.dshackle.upstream.RecursiveLowerBoundBlockDetector import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.toHex import reactor.core.publisher.Mono @@ -23,7 +24,7 @@ class PolkadotLowerBoundBlockDetector( return upstream.getIngressReader().read( JsonRpcRequest( "chain_getBlockHash", - listOf(blockNumber.toHex()), // in polkadot state methods work only with hash + ListParams(blockNumber.toHex()), // in polkadot state methods work only with hash ), ) .flatMap(JsonRpcResponse::requireResult) @@ -34,7 +35,7 @@ class PolkadotLowerBoundBlockDetector( upstream.getIngressReader().read( JsonRpcRequest( "state_getMetadata", - listOf(it), + ListParams(it), ), ) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/CallParams.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/CallParams.kt new file mode 100644 index 00000000..3c533c60 --- /dev/null +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/CallParams.kt @@ -0,0 +1,11 @@ +package io.emeraldpay.dshackle.upstream.rpcclient + +sealed interface CallParams + +data class ListParams(val list: List) : CallParams { + constructor(vararg elements: Any) : this(listOf(*elements)) + constructor() : this(listOf()) +} +data class ObjectParams(val obj: Map) : CallParams { + constructor(vararg pairs: Pair) : this(mapOf(*pairs)) +} diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClient.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClient.kt index 4f1defaa..42ad1350 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClient.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClient.kt @@ -61,7 +61,16 @@ class JsonRpcGrpcClient( val reqItem = BlockchainOuterClass.NativeCallItem.newBuilder() .setId(1) .setMethod(key.method) - .setPayload(ByteString.copyFrom(Global.objectMapper.writeValueAsBytes(key.params))) + .setPayload( + ByteString.copyFrom( + Global.objectMapper.writeValueAsBytes( + when (key.params) { + is ListParams -> key.params.list + is ObjectParams -> key.params.obj + }, + ), + ), + ) if (key.nonce != null) { reqItem.nonce = key.nonce } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequest.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequest.kt index 1e28ad0a..853f9ba7 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequest.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequest.kt @@ -24,33 +24,30 @@ import io.emeraldpay.dshackle.Global data class JsonRpcRequest( val method: String, - val params: List, + val params: CallParams, val id: Int, val nonce: Long?, val selector: BlockchainOuterClass.Selector?, val isStreamed: Boolean = false, - val objParams: Map? = null, ) { @JvmOverloads constructor( method: String, - params: List, + params: CallParams, nonce: Long? = null, selectors: BlockchainOuterClass.Selector? = null, isStreamed: Boolean = false, ) : this(method, params, 1, nonce, selectors, isStreamed) - constructor( - method: String, - objParams: Map, - ) : this(method, listOf(), 1, null, null, false, objParams) - fun toJson(): ByteArray { val json = mapOf( "jsonrpc" to "2.0", "id" to id, "method" to method, - "params" to (objParams ?: params), + "params" to when (params) { + is ListParams -> params.list + is ObjectParams -> params.obj + }, ) return Global.objectMapper.writeValueAsBytes(json) } @@ -59,6 +56,7 @@ data class JsonRpcRequest( return String(this.toJson()) } + @Suppress("UNCHECKED_CAST") class Deserializer : JsonDeserializer() { override fun deserialize(p: JsonParser, ctxt: DeserializationContext): JsonRpcRequest { @@ -78,7 +76,7 @@ data class JsonRpcRequest( throw IllegalStateException("Unsupported param type: ${it.asToken()}") } } - return JsonRpcRequest(method, params, id, null, null) + return JsonRpcRequest(method, ListParams(params as List), id, null, null) } } } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaChainSpecific.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaChainSpecific.kt index 73105f9b..8ef50374 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaChainSpecific.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaChainSpecific.kt @@ -25,6 +25,7 @@ import io.emeraldpay.dshackle.upstream.generic.GenericEgressSubscription import io.emeraldpay.dshackle.upstream.generic.GenericIngressSubscription import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import reactor.core.publisher.Mono import reactor.core.scheduler.Scheduler @@ -36,12 +37,12 @@ object SolanaChainSpecific : AbstractChainSpecific() { private val log = LoggerFactory.getLogger(SolanaChainSpecific::class.java) override fun getLatestBlock(api: JsonRpcReader, upstreamId: String): Mono { - return api.read(JsonRpcRequest("getSlot", listOf())).flatMap { + return api.read(JsonRpcRequest("getSlot", ListParams())).flatMap { val slot = it.getResultAsProcessedString().toLong() api.read( JsonRpcRequest( "getBlocks", - listOf( + ListParams( slot - 10, slot, ), @@ -54,7 +55,7 @@ object SolanaChainSpecific : AbstractChainSpecific() { api.read( JsonRpcRequest( "getBlock", - listOf( + ListParams( response.max(), mapOf( "showRewards" to false, @@ -100,7 +101,7 @@ object SolanaChainSpecific : AbstractChainSpecific() { override fun listenNewHeadsRequest(): JsonRpcRequest { return JsonRpcRequest( "blockSubscribe", - listOf( + ListParams( "all", mapOf( "showRewards" to false, @@ -111,7 +112,7 @@ object SolanaChainSpecific : AbstractChainSpecific() { } override fun unsubscribeNewHeadsRequest(subId: String): JsonRpcRequest { - return JsonRpcRequest("blockUnsubscribe", listOf(subId)) + return JsonRpcRequest("blockUnsubscribe", ListParams(subId)) } override fun validator( @@ -124,7 +125,7 @@ object SolanaChainSpecific : AbstractChainSpecific() { upstream, options, SingleCallValidator( - JsonRpcRequest("getHealth", listOf()), + JsonRpcRequest("getHealth", ListParams()), ) { data -> val resp = String(data) if (resp == "\"ok\"") { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetector.kt index 761aaedf..4aa77152 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetector.kt @@ -6,6 +6,7 @@ import io.emeraldpay.dshackle.upstream.LowerBoundBlockDetector import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Mono import reactor.util.retry.Retry import java.time.Duration @@ -21,7 +22,7 @@ class SolanaLowerBoundBlockDetector( return Mono.just(reader) .flatMap { it.read( - JsonRpcRequest("getFirstAvailableBlock", listOf()), // in case of solana we talk about the slot of the lowest confirmed block + JsonRpcRequest("getFirstAvailableBlock", ListParams()), // in case of solana we talk about the slot of the lowest confirmed block ) } .flatMap(JsonRpcResponse::requireResult) @@ -37,7 +38,7 @@ class SolanaLowerBoundBlockDetector( reader.read( JsonRpcRequest( "getBlock", // since getFirstAvailableBlock returns the slot of the lowest confirmed block we can directly call getBlock - listOf( + ListParams( it, mapOf( "showRewards" to false, diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetChainSpecific.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetChainSpecific.kt index 7891912b..ea05fed3 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetChainSpecific.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetChainSpecific.kt @@ -16,6 +16,7 @@ import io.emeraldpay.dshackle.upstream.UpstreamValidator import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.slf4j.LoggerFactory import java.math.BigInteger import java.time.Instant @@ -63,7 +64,7 @@ object StarknetChainSpecific : AbstractPollChainSpecific() { upstream, options, SingleCallValidator( - JsonRpcRequest("starknet_syncing", listOf()), + JsonRpcRequest("starknet_syncing", ListParams()), ) { data -> validate(data, config.laggingLagSize, upstream.getId()) }, @@ -93,7 +94,7 @@ object StarknetChainSpecific : AbstractPollChainSpecific() { } override fun latestBlockRequest(): JsonRpcRequest = - JsonRpcRequest("starknet_getBlockWithTxHashes", listOf("latest")) + JsonRpcRequest("starknet_getBlockWithTxHashes", ListParams("latest")) } @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/src/test/groovy/io/emeraldpay/dshackle/quorum/QuorumRpcReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/quorum/QuorumRpcReaderSpec.groovy index 77b53e91..98cac6fa 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/quorum/QuorumRpcReaderSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/quorum/QuorumRpcReaderSpec.groovy @@ -24,6 +24,7 @@ import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError import org.springframework.cloud.sleuth.Tracer @@ -42,7 +43,7 @@ class QuorumRpcReaderSpec extends Specification { _ * getId() >> "id" _ * getRole() >> UpstreamsConfig.UpstreamRole.PRIMARY 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_test", [])) >> Mono.just(JsonRpcResponse.ok("1")) + 1 * read(new JsonRpcRequest("eth_test", new ListParams())) >> Mono.just(JsonRpcResponse.ok("1")) } } def apis = new FilteredApis( @@ -52,7 +53,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new AlwaysQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -67,7 +68,7 @@ class QuorumRpcReaderSpec extends Specification { def "always-quorum - return upstream error returned"() { setup: def api = Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_test", [])) >>> [ + 1 * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.just(JsonRpcResponse.error(1, "test")) ] } @@ -84,7 +85,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new AlwaysQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -100,7 +101,7 @@ class QuorumRpcReaderSpec extends Specification { def "always-quorum - return upstream error thrown"() { setup: def api = Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_test", [])) >>> [ + 1 * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.error( new RpcException( RpcResponseError.CODE_UPSTREAM_CONNECTION_ERROR, @@ -122,7 +123,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new AlwaysQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -142,7 +143,7 @@ class QuorumRpcReaderSpec extends Specification { _ * getId() >> "id" _ * getRole() >> UpstreamsConfig.UpstreamRole.PRIMARY _ * getIngressReader() >> Mock(Reader) { - 2 * read(new JsonRpcRequest("eth_test", [])) >>> [ + 2 * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.just(JsonRpcResponse.ok("null")), Mono.just(JsonRpcResponse.ok("1")) ] @@ -155,7 +156,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new NotNullQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -175,7 +176,7 @@ class QuorumRpcReaderSpec extends Specification { _ * getId() >> "id" _ * getRole() >> UpstreamsConfig.UpstreamRole.PRIMARY _ * getIngressReader() >> Mock(Reader) { - 2 * read(new JsonRpcRequest("eth_test", [])) >>> [ + 2 * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.just(JsonRpcResponse.error(1, "test")), Mono.just(JsonRpcResponse.ok("1")) ] @@ -188,7 +189,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new NotNullQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -203,7 +204,7 @@ class QuorumRpcReaderSpec extends Specification { def "non-empty-quorum - error if all failed"() { setup: def api = Mock(Reader) { - 2 * read(new JsonRpcRequest("eth_test", [])) >>> [ + 2 * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.just(JsonRpcResponse.error(1, "test")), Mono.just(JsonRpcResponse.error(1, "test")), ] @@ -221,7 +222,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new NotNullQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -235,7 +236,7 @@ class QuorumRpcReaderSpec extends Specification { def "always-quorum - error if failed"() { setup: def api = Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_test", [])) >>> [ + 1 * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.just(JsonRpcResponse.error(1, "test error")), ] } @@ -252,7 +253,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new AlwaysQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } @@ -274,7 +275,7 @@ class QuorumRpcReaderSpec extends Specification { _ * isAvailable() >> true _ * getRole() >> UpstreamsConfig.UpstreamRole.PRIMARY _ * getIngressReader() >> Mock(Reader) { - _ * read(new JsonRpcRequest("eth_test", [])) >>> [ + _ * read(new JsonRpcRequest("eth_test", new ListParams())) >>> [ Mono.just(JsonRpcResponse.error(-3010, "test")), ] } @@ -286,7 +287,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new NotLaggingQuorum(1), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) then: StepVerifier.create(act) @@ -312,7 +313,7 @@ class QuorumRpcReaderSpec extends Specification { def reader = new QuorumRpcReader(apis, new AlwaysQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_test", [])) + def act = reader.read(new JsonRpcRequest("eth_test", new ListParams())) .map { new String(it.value) } diff --git a/src/test/groovy/io/emeraldpay/dshackle/reader/BroadcastReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/reader/BroadcastReaderSpec.groovy index 29760b7a..f426dbf0 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/reader/BroadcastReaderSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/reader/BroadcastReaderSpec.groovy @@ -6,6 +6,7 @@ import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.springframework.cloud.sleuth.Tracer import reactor.core.publisher.Mono import reactor.test.StepVerifier @@ -22,7 +23,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.just(new JsonRpcResponse(result, null)) } } @@ -30,7 +31,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.just(new JsonRpcResponse(result, null)) } } @@ -38,13 +39,13 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.just(new JsonRpcResponse(result, null)) } } def reader = new BroadcastReader([up, up1, up2], new Selector.EmptyMatcher(), null, new BroadcastQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) + def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) then: StepVerifier.create(act) .expectNextMatches { @@ -61,7 +62,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.just(new JsonRpcResponse(result, null)) } } @@ -69,7 +70,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.error(new JsonRpcException(1, "too low")) } } @@ -77,12 +78,12 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.error(new JsonRpcException(1, "too low")) } } def reader = new BroadcastReader([up, up1, up2], new Selector.EmptyMatcher(), null, new BroadcastQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) + def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) then: StepVerifier.create(act) .expectNextMatches { @@ -99,7 +100,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.just(new JsonRpcResponse(result, null)) } } @@ -115,7 +116,7 @@ class BroadcastReaderSpec extends Specification { } def reader = new BroadcastReader([up, up1, up2], new Selector.EmptyMatcher(), null, new BroadcastQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) + def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) then: StepVerifier.create(act) .expectNextMatches { @@ -131,7 +132,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.error(new JsonRpcException(1, "too low")) } } @@ -139,7 +140,7 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.error(new JsonRpcException(1, "too low")) } } @@ -147,13 +148,13 @@ class BroadcastReaderSpec extends Specification { 1 * isAvailable() >> true _ * getId() >> "id" 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) >> + 1 * read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) >> Mono.error(new JsonRpcException(1, "too low")) } } def reader = new BroadcastReader([up, up1, up2], new Selector.EmptyMatcher(), null, new BroadcastQuorum(), Stub(Tracer)) when: - def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) + def act = reader.read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) then: StepVerifier.create(act) .expectError(JsonRpcException.class) @@ -180,7 +181,7 @@ class BroadcastReaderSpec extends Specification { def reader = new BroadcastReader([up, up1, up2], new Selector.EmptyMatcher(), null, new BroadcastQuorum(), Stub(Tracer)) when: def act = reader - .read(new JsonRpcRequest("eth_sendRawTransaction", ["0x1"])) + .read(new JsonRpcRequest("eth_sendRawTransaction", new ListParams(["0x1"]))) .switchIfEmpty(Mono.just(new RpcReader.Result(new byte[0], null, 0, null, null))) then: StepVerifier.create(act) diff --git a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy index ec33518e..9a562a89 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy @@ -39,6 +39,7 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.signature.ResponseSigner import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError @@ -75,7 +76,7 @@ class NativeCallSpec extends Specification { def "Tries router first"() { def routedApi = Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_test", [])) >> Mono.just(new JsonRpcResponse("1".bytes, null)) + 1 * read(new JsonRpcRequest("eth_test", new ListParams())) >> Mono.just(new JsonRpcResponse("1".bytes, null)) } def upstream = Mock(Multistream) { 1 * getLocalReader() >> Mono.just(routedApi) @@ -84,7 +85,7 @@ class NativeCallSpec extends Specification { def nativeCall = nativeCall() def ctx = new NativeCall.ValidCallContext( 1, null, upstream, Selector.empty, new AlwaysQuorum(), - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1 + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1 ) when: @@ -96,7 +97,7 @@ class NativeCallSpec extends Specification { def "Return error if router denied the requests"() { def routedApi = Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_test", [])) >> Mono.error(new RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Test message")) + 1 * read(new JsonRpcRequest("eth_test", new ListParams())) >> Mono.error(new RpcException(RpcResponseError.CODE_METHOD_NOT_EXIST, "Test message")) } def upstream = Mock(Multistream) { 1 * getLocalReader() >> Mono.just(routedApi) @@ -105,7 +106,7 @@ class NativeCallSpec extends Specification { def nativeCall = nativeCall() def ctx = new NativeCall.ValidCallContext( 15, null, upstream, Selector.empty, new AlwaysQuorum(), - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1 + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1 ) when: @@ -134,7 +135,7 @@ class NativeCallSpec extends Specification { } } def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum, - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1) + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1) when: def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1)) @@ -152,11 +153,11 @@ class NativeCallSpec extends Specification { nativeCall.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { 1 * attempts() >> new AtomicInteger(1) - 1 * read(new JsonRpcRequest("eth_test", [], 10)) >> Mono.empty() + 1 * read(new JsonRpcRequest("eth_test", new ListParams(), 10)) >> Mono.empty() } } def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum, - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1) + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1) when: def resp = nativeCall.executeOnRemote(call) @@ -176,13 +177,13 @@ class NativeCallSpec extends Specification { def nativeCall = nativeCall() nativeCall.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_test", [], 10)) >> Mono.error( + 1 * read(new JsonRpcRequest("eth_test", new ListParams(), 10)) >> Mono.error( new JsonRpcException(JsonRpcResponse.Id.from(12), new JsonRpcError(-32123, "Foo Bar", "Foo Bar Baz"), null, true, null) ) } } def call = new NativeCall.ValidCallContext(12, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum, - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1) + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1) when: def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1)) @@ -536,7 +537,7 @@ class NativeCallSpec extends Specification { def act = nativeCall.parseParams(ctx) then: act.id == 1 - act.payload.params == [] + act.payload.params == new ListParams() act.payload.method == "eth_test" } @@ -549,7 +550,7 @@ class NativeCallSpec extends Specification { def act = nativeCall.parseParams(ctx) then: act.id == 1 - act.payload.params == [] + act.payload.params == new ListParams() act.payload.method == "eth_test" } @@ -562,7 +563,7 @@ class NativeCallSpec extends Specification { def act = nativeCall.parseParams(ctx) then: act.id == 1 - act.payload.params == [false] + act.payload.params == new ListParams([false]) act.payload.method == "eth_test" } @@ -575,7 +576,7 @@ class NativeCallSpec extends Specification { def act = nativeCall.parseParams(ctx) then: act.id == 1 - act.payload.params == [false, 123] + act.payload.params == new ListParams([false, 123]) act.payload.method == "eth_test" } @@ -589,7 +590,7 @@ class NativeCallSpec extends Specification { def act = nativeCall.parseParams(ctx) then: act.id == 1 - act.payload.params == ["0xab"] + act.payload.params == new ListParams(["0xab"]) act.payload.method == "eth_getFilterUpdates" } @@ -618,7 +619,7 @@ class NativeCallSpec extends Specification { } } def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum, - new NativeCall.ParsedCallDetails("eth_getFilterChanges", []), + new NativeCall.ParsedCallDetails("eth_getFilterChanges", new ListParams()), new NativeCall.WithFilterIdDecorator(), new NativeCall.CreateFilterDecorator(), null, false, "reqId", 1) when: @@ -654,7 +655,7 @@ class NativeCallSpec extends Specification { } } def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum, - new NativeCall.ParsedCallDetails("eth_getFilterChanges", []), + new NativeCall.ParsedCallDetails("eth_getFilterChanges", new ListParams()), new NativeCall.WithFilterIdDecorator(), new NativeCall.CreateFilterDecorator(), null, false, "reqId", 1) when: @@ -676,7 +677,7 @@ class NativeCallSpec extends Specification { def ctx = new NativeCall.ValidCallContext(10, null, upstream, Selector.empty, new AlwaysQuorum(), - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1) + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1) when: nativeCall.fetch(ctx) then: @@ -693,7 +694,7 @@ class NativeCallSpec extends Specification { def ctx = new NativeCall.ValidCallContext(10, null, upstream, Selector.empty, new AlwaysQuorum(), - new NativeCall.ParsedCallDetails("eth_test", []), "reqId", 1) + new NativeCall.ParsedCallDetails("eth_test", new ListParams()), "reqId", 1) when: def act = nativeCall.fetch(ctx) then: diff --git a/src/test/groovy/io/emeraldpay/dshackle/test/ApiReaderMock.groovy b/src/test/groovy/io/emeraldpay/dshackle/test/ApiReaderMock.groovy index 7d1f6ac7..880a458b 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/test/ApiReaderMock.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/test/ApiReaderMock.groovy @@ -81,7 +81,7 @@ class ApiReaderMock implements Reader { @Override Mono read(JsonRpcRequest request, boolean required = true) { Callable call = { - def predefined = predefined.find { it.isSame(request.method, request.params) } + def predefined = predefined.find { it.isSame(request.method, request.params.list) } byte[] result = null JsonRpcError error = null calls.incrementAndGet() diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHeadSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHeadSpec.groovy index 45a1cebf..87be360e 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHeadSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcHeadSpec.groovy @@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.bitcoin import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Mono import reactor.core.scheduler.Schedulers import reactor.test.StepVerifier @@ -78,13 +79,13 @@ class BitcoinRpcHeadSpec extends Specification { """ def api = Mock(Reader) { - _ * read(new JsonRpcRequest("getbestblockhash", [])) >>> [ + _ * read(new JsonRpcRequest("getbestblockhash", new ListParams())) >>> [ Mono.just(new JsonRpcResponse("\"$hash1\"".bytes, null)), Mono.just(new JsonRpcResponse("\"$hash1\"".bytes, null)), Mono.just(new JsonRpcResponse("\"$hash2\"".bytes, null)) ] - _ * read(new JsonRpcRequest("getblock", [hash1])) >> Mono.just(new JsonRpcResponse(block1.bytes, null)) - _ * read(new JsonRpcRequest("getblock", [hash2])) >> Mono.just(new JsonRpcResponse(block2.bytes, null)) + _ * read(new JsonRpcRequest("getblock", new ListParams([hash1]))) >> Mono.just(new JsonRpcResponse(block1.bytes, null)) + _ * read(new JsonRpcRequest("getblock", new ListParams([hash2]))) >> Mono.just(new JsonRpcResponse(block2.bytes, null)) } BitcoinRpcHead head = new BitcoinRpcHead(api, new ExtractBlock(), Duration.ofMillis(200), Schedulers.boundedElastic()) diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReaderSpec.groovy index e47df718..25c48b08 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReaderSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/bitcoin/RpcUnspentReaderSpec.groovy @@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.bitcoin import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.bitcoinj.core.Address import org.bitcoinj.params.MainNetParams import reactor.core.publisher.Mono @@ -29,7 +30,7 @@ class RpcUnspentReaderSpec extends Specification { setup: def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-one-addr.json").bytes def rpcReader = Mock(Reader) { - 1 * read(new JsonRpcRequest("listunspent", [1, 9999999, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"]])) >> Mono.just(JsonRpcResponse.ok(json)) + 1 * read(new JsonRpcRequest("listunspent", new ListParams([1, 9999999, ["1K7xkspJg7DDKNwzXgoRSDCUxiFsRegsSK"]]))) >> Mono.just(JsonRpcResponse.ok(json)) } def upstreams = Mock(BitcoinMultistream) { 1 * getDirectApi(_) >> Mono.just(rpcReader) @@ -63,7 +64,7 @@ class RpcUnspentReaderSpec extends Specification { setup: def json = this.class.getClassLoader().getResourceAsStream("bitcoin/unspent-two-addr.json").bytes def rpcReader = Mock(Reader) { - 1 * read(new JsonRpcRequest("listunspent", [1, 9999999, ["35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP"]])) >> Mono.just(JsonRpcResponse.ok(json)) + 1 * read(new JsonRpcRequest("listunspent", new ListParams([1, 9999999, ["35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP"]]))) >> Mono.just(JsonRpcResponse.ok(json)) } def upstreams = Mock(BitcoinMultistream) { 1 * getDirectApi(_) >> Mono.just(rpcReader) diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumCachingReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumCachingReaderSpec.groovy index 14299e79..501135f0 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumCachingReaderSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumCachingReaderSpec.groovy @@ -13,6 +13,7 @@ import io.emeraldpay.dshackle.upstream.* import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods import io.emeraldpay.dshackle.upstream.ethereum.json.BlockJson import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.ethereum.domain.Address import io.emeraldpay.dshackle.upstream.ethereum.domain.BlockHash import io.emeraldpay.dshackle.upstream.ethereum.domain.TransactionId @@ -52,7 +53,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getBlockByHash", new ListParams([hash1, false]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(json), null, 1, resolver, null) ) @@ -79,7 +80,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getBlockByHash", new ListParams([hash1, false]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(null), null, 1, resolver, null ) @@ -112,7 +113,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x64", false])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x64", false]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(json), null, 1, resolver, null ) @@ -144,7 +145,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getLogs", [Map.of("blockHash", hash1)])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getLogs", new ListParams([Map.of("blockHash", hash1)]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes([json]), null, 1, resolver, null ) @@ -177,7 +178,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getTransactionByHash", [hash1])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getTransactionByHash", new ListParams([hash1]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(json), null, 1, resolver, null ) @@ -210,7 +211,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getTransactionReceipt", [hash1])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getTransactionReceipt", new ListParams([hash1]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(json), null, 1, resolver, null ) @@ -244,7 +245,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getTransactionReceipt", [hash1])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getTransactionReceipt", new ListParams([hash1]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(json), null, 1, resolver, null ) @@ -269,7 +270,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getTransactionByHash", [hash1])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getTransactionByHash", new ListParams([hash1]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes(null), null, 1, resolver, null ) @@ -299,7 +300,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBalance", [address1, "latest"])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getBalance", new ListParams([address1, "latest"]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes("0x100"), null, 1, resolver, null ) @@ -330,7 +331,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBalance", [address1, "0xa8c9bb"])) >> Mono.just( + 1 * read(new JsonRpcRequest("eth_getBalance", new ListParams([address1, "0xa8c9bb"]))) >> Mono.just( new RpcReader.Result( Global.objectMapper.writeValueAsBytes("0x100"), null, 1, resolver, null ) @@ -368,11 +369,11 @@ class EthereumDirectReaderSpec extends Specification { ) ethereumDirectReader.rpcReaderFactory = Mock(RpcReaderFactory) { 2 * create(_) >> Mock(RpcReader) { - 2 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >>> + 2 * read(new JsonRpcRequest("eth_getBlockByHash", new ListParams([hash1, false]))) >>> [Mono.error(new RuntimeException()), Mono.error(new RuntimeException())] } 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> result + 1 * read(new JsonRpcRequest("eth_getBlockByHash", new ListParams([hash1, false]))) >> result } } when: @@ -408,11 +409,11 @@ class EthereumDirectReaderSpec extends Specification { ) ethereumDirectReader.rpcReaderFactory = Mock(RpcReaderFactory) { 2 * create(_) >> Mock(RpcReader) { - 2 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x64", false])) >>> + 2 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x64", false]))) >>> [Mono.error(new RuntimeException()), Mono.error(new RuntimeException())] } 1 * create(_) >> Mock(RpcReader) { - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x64", false])) >> result + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x64", false]))) >> result } } when: @@ -441,7 +442,7 @@ class EthereumDirectReaderSpec extends Specification { ) reader.rpcReaderFactory = Mock(RpcReaderFactory) { 4 * create(_) >> Mock(RpcReader) { - 4 * read(new JsonRpcRequest("eth_getBalance", [address1, "latest"])) >>> + 4 * read(new JsonRpcRequest("eth_getBalance", new ListParams([address1, "latest"]))) >>> [Mono.error(new RuntimeException()), Mono.error(new RuntimeException()), Mono.error(new RuntimeException()), Mono.error(new RuntimeException())] } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy index 48983254..b5d2f12b 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy @@ -8,6 +8,7 @@ import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.ethereum.subscribe.EthereumLabelsDetector import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import kotlin.Pair import reactor.core.publisher.Mono import reactor.test.StepVerifier @@ -52,13 +53,13 @@ class EthereumLabelsDetectorSpec extends Specification { setup: def up = Mock(DefaultUpstream) { 1 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("web3_clientVersion", [])) >> + 1 * read(new JsonRpcRequest("web3_clientVersion", new ListParams())) >> Mono.just(new JsonRpcResponse('no/v1.19.3+e8ac1da4/linux-x64/dotnet7.0.8'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse("\"0x10df3e5\"".getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"])) >> + 1 * read(new JsonRpcRequest("eth_getBalance", new ListParams(["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"]))) >> Mono.error(new RuntimeException()) - 1 * read(new JsonRpcRequest("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x2710"])) >> + 1 * read(new JsonRpcRequest("eth_getBalance", new ListParams(["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x2710"]))) >> Mono.just(new JsonRpcResponse("".getBytes(), null)) } } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReaderSpec.groovy index f4fd4602..8c04c378 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReaderSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLocalReaderSpec.groovy @@ -10,6 +10,7 @@ import io.emeraldpay.dshackle.upstream.EmptyHead import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.ethereum.json.BlockJson import org.apache.commons.collections4.functors.ConstantFactory import reactor.core.publisher.Mono @@ -34,7 +35,7 @@ class EthereumLocalReaderSpec extends Specification { null ) when: - def act = router.read(new JsonRpcRequest("eth_coinbase", [])).block(Duration.ofSeconds(1)) + def act = router.read(new JsonRpcRequest("eth_coinbase", new ListParams())).block(Duration.ofSeconds(1)) then: act.resultAsProcessedString == "0x0000000000000000000000000000000000000000" } @@ -54,7 +55,7 @@ class EthereumLocalReaderSpec extends Specification { null ) when: - def act = router.read(new JsonRpcRequest("eth_getTransactionByHash", ["test"], 10)) + def act = router.read(new JsonRpcRequest("eth_getTransactionByHash", new ListParams(["test"]), 10)) .block(Duration.ofSeconds(1)) then: act == null diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidatorSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidatorSpec.groovy index 08228814..28f3db1d 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidatorSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumUpstreamValidatorSpec.groovy @@ -24,6 +24,7 @@ import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.ethereum.domain.Address import io.emeraldpay.dshackle.upstream.ethereum.hex.HexData @@ -41,7 +42,6 @@ import static io.emeraldpay.dshackle.upstream.UpstreamAvailability.* import static io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult.UPSTREAM_FATAL_SETTINGS_ERROR import static io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult.UPSTREAM_SETTINGS_ERROR import static io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult.UPSTREAM_VALID -import static java.util.Collections.emptyList import io.emeraldpay.dshackle.config.ChainsConfig.ChainConfig class EthereumUpstreamValidatorSpec extends Specification { @@ -280,8 +280,8 @@ class EthereumUpstreamValidatorSpec extends Specification { def up = Mock(Upstream) { 2 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } @@ -300,12 +300,12 @@ class EthereumUpstreamValidatorSpec extends Specification { }.buildOptions() def up = Mock(Upstream) { 3 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_call", [new TransactionCallJson( + 1 * read(new JsonRpcRequest("eth_call", new ListParams([new TransactionCallJson( Address.from("0x32268860cAAc2948Ab5DdC7b20db5a420467Cf96"), HexData.from("0xd8a26e3a00000000000000000000000000000000000000000000000000000000000f4240") - ), "latest"])) >> Mono.just(new JsonRpcResponse("0x00000000000000000000".getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + ), "latest"]))) >> Mono.just(new JsonRpcResponse("0x00000000000000000000".getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } @@ -324,12 +324,12 @@ class EthereumUpstreamValidatorSpec extends Specification { }.buildOptions() def up = Mock(Upstream) { 3 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_call", [new TransactionCallJson( + 1 * read(new JsonRpcRequest("eth_call", new ListParams([new TransactionCallJson( Address.from("0x32268860cAAc2948Ab5DdC7b20db5a420467Cf96"), HexData.from("0xd8a26e3a00000000000000000000000000000000000000000000000000000000000f4240") - ), "latest"])) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + ), "latest"]))) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } @@ -348,10 +348,10 @@ class EthereumUpstreamValidatorSpec extends Specification { }.buildOptions() def up = Mock(Upstream) { 4 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_chainId", emptyList())) >> Mono.just(new JsonRpcResponse('"0x1"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("net_version", emptyList())) >> Mono.just(new JsonRpcResponse('"1"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + 1 * read(new JsonRpcRequest("eth_chainId", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x1"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("net_version", new ListParams())) >> Mono.just(new JsonRpcResponse('"1"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } @@ -370,10 +370,10 @@ class EthereumUpstreamValidatorSpec extends Specification { }.buildOptions() def up = Mock(Upstream) { 4 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_chainId", emptyList())) >> Mono.just(new JsonRpcResponse('"0x1"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("net_version", emptyList())) >> Mono.just(new JsonRpcResponse('"1"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + 1 * read(new JsonRpcRequest("eth_chainId", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x1"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("net_version", new ListParams())) >> Mono.just(new JsonRpcResponse('"1"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } @@ -390,14 +390,14 @@ class EthereumUpstreamValidatorSpec extends Specification { def options = ChainOptions.PartialOptions.getDefaults().buildOptions() def up = Mock(Upstream) { 5 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_chainId", emptyList())) >> Mono.just(new JsonRpcResponse('"0x1"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("net_version", emptyList())) >> Mono.just(new JsonRpcResponse('"1"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_call", [new TransactionCallJson( + 1 * read(new JsonRpcRequest("eth_chainId", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x1"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("net_version", new ListParams())) >> Mono.just(new JsonRpcResponse('"1"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_call", new ListParams([new TransactionCallJson( Address.from("0x32268860cAAc2948Ab5DdC7b20db5a420467Cf96"), HexData.from("0xd8a26e3a00000000000000000000000000000000000000000000000000000000000f4240") - ), "latest"])) >> Mono.just(new JsonRpcResponse("0x00000000000000000000".getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + ), "latest"]))) >> Mono.just(new JsonRpcResponse("0x00000000000000000000".getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } @@ -414,14 +414,14 @@ class EthereumUpstreamValidatorSpec extends Specification { def options = ChainOptions.PartialOptions.getDefaults().buildOptions() def up = Mock(Upstream) { 5 * getIngressReader() >> Mock(Reader) { - 1 * read(new JsonRpcRequest("eth_chainId", emptyList())) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) - 1 * read(new JsonRpcRequest("net_version", emptyList())) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) - 1 * read(new JsonRpcRequest("eth_call", [new TransactionCallJson( + 1 * read(new JsonRpcRequest("eth_chainId", new ListParams())) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) + 1 * read(new JsonRpcRequest("net_version", new ListParams())) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) + 1 * read(new JsonRpcRequest("eth_call", new ListParams([new TransactionCallJson( Address.from("0x32268860cAAc2948Ab5DdC7b20db5a420467Cf96"), HexData.from("0xd8a26e3a00000000000000000000000000000000000000000000000000000000000f4240") - ), "latest"])) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) - 1 * read(new JsonRpcRequest("eth_blockNumber", [])) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) - 1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x10fd2ae", false])) >> + ), "latest"]))) >> Mono.just(new JsonRpcResponse(null, new JsonRpcError(1, "Too long"))) + 1 * read(new JsonRpcRequest("eth_blockNumber", new ListParams())) >> Mono.just(new JsonRpcResponse('"0x10ff9be"'.getBytes(), null)) + 1 * read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams(["0x10fd2ae", false]))) >> Mono.just(new JsonRpcResponse('"result"'.getBytes(), null)) } } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/GenericWsHeadSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/GenericWsHeadSpec.groovy index 8e102308..432778e2 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/GenericWsHeadSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/GenericWsHeadSpec.groovy @@ -27,6 +27,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.json.BlockJson import io.emeraldpay.dshackle.upstream.forkchoice.AlwaysForkChoice import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.ethereum.domain.BlockHash import io.emeraldpay.dshackle.upstream.ethereum.json.TransactionRefJson import reactor.core.publisher.Flux @@ -61,7 +62,7 @@ class GenericWsHeadSpec extends Specification { } def reader = Mock(Reader) { - 1 * it.read(new JsonRpcRequest("eth_getBlockByNumber", List.of("latest", false))) >> Mono.empty() + 1 * it.read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams("latest", false))) >> Mono.empty() } def ws = Mock(WsSubscriptions) { @@ -338,7 +339,7 @@ class GenericWsHeadSpec extends Specification { block.totalDifficulty = BigInteger.ONE def reader = Mock(Reader) { - 1 * it.read(new JsonRpcRequest("eth_getBlockByNumber", List.of("latest", false))) >> Mono.empty() + 1 * it.read(new JsonRpcRequest("eth_getBlockByNumber", new ListParams("latest", false))) >> Mono.empty() } def subId = "subId" def ws = Mock(WsSubscriptions) { @@ -346,7 +347,7 @@ class GenericWsHeadSpec extends Specification { 1 * it.subscribe(_) >> new WsSubscriptions.SubscribeData( Flux.error(new RuntimeException()), "id", new AtomicReference(subId) ) - 1 * it.unsubscribe(new JsonRpcRequest("eth_unsubscribe", List.of(subId), 2, null, null, false)) >> + 1 * it.unsubscribe(new JsonRpcRequest("eth_unsubscribe", new ListParams(subId), 2, null, null, false)) >> Mono.just(new JsonRpcResponse("".bytes, null)) } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplRealSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplRealSpec.groovy index f44a9c9f..3249e6e4 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplRealSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplRealSpec.groovy @@ -6,6 +6,7 @@ import io.emeraldpay.dshackle.test.MockWSServer import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.scheduler.Schedulers import reactor.test.StepVerifier import spock.lang.Shared @@ -55,7 +56,7 @@ class WsConnectionImplRealSpec extends Specification { def "Can make a RPC request"() { when: conn.connect() - def resp = conn.callRpc(new JsonRpcRequest("foo_bar", [])) + def resp = conn.callRpc(new JsonRpcRequest("foo_bar", new ListParams())) then: StepVerifier.create(resp) .then { @@ -87,7 +88,7 @@ class WsConnectionImplRealSpec extends Specification { server.onNextReply('{"jsonrpc":"2.0","id":100,"result":1}') // reconnects in 2 seconds, give 1 extra Thread.sleep(3_000) - def resp = conn.callRpc(new JsonRpcRequest("foo_bar", [])).block(Duration.ofSeconds(1)) + def resp = conn.callRpc(new JsonRpcRequest("foo_bar", new ListParams())).block(Duration.ofSeconds(1)) def act = server.received then: @@ -100,7 +101,7 @@ class WsConnectionImplRealSpec extends Specification { conn.connect() conn.reconnectIntervalSeconds = 2 - def resp = conn.callRpc(new JsonRpcRequest("foo_bar", [])) + def resp = conn.callRpc(new JsonRpcRequest("foo_bar", new ListParams())) then: StepVerifier.create(resp) @@ -121,7 +122,7 @@ class WsConnectionImplRealSpec extends Specification { server.onNextReply('{"jsonrpc":"2.0","id":100,"result":1}') Thread.sleep(3_000) - def resp = conn.callRpc(new JsonRpcRequest("foo_bar", [])).block(Duration.ofSeconds(1)) + def resp = conn.callRpc(new JsonRpcRequest("foo_bar", new ListParams())).block(Duration.ofSeconds(1)) def act = server.received then: act.size() == 1 @@ -140,7 +141,7 @@ class WsConnectionImplRealSpec extends Specification { // reconnects in 2 seconds, give 1 extra Thread.sleep(3_000) - def resp = conn.callRpc(new JsonRpcRequest("foo_bar", [])) + def resp = conn.callRpc(new JsonRpcRequest("foo_bar", new ListParams())) then: StepVerifier.create(resp) .then { diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplSpec.groovy index cdebff86..e4d799db 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsConnectionImplSpec.groovy @@ -21,6 +21,7 @@ import io.emeraldpay.dshackle.test.GenericUpstreamMock import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.upstream.DefaultUpstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.ethereum.domain.TransactionId import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError import io.emeraldpay.dshackle.upstream.ethereum.json.TransactionJson @@ -58,7 +59,7 @@ class WsConnectionImplSpec extends Specification { when: Flux.from(ws.handle(wsApiMock.inbound, wsApiMock.outbound)).subscribe() - def act = ws.callRpc(new JsonRpcRequest("eth_getTransactionByHash", ["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"], 15, null, null, false)) + def act = ws.callRpc(new JsonRpcRequest("eth_getTransactionByHash", new ListParams(["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"]), 15, null, null, false)) then: StepVerifier.create(act) @@ -90,7 +91,7 @@ class WsConnectionImplSpec extends Specification { when: Flux.from(ws.handle(wsApiMock.inbound, wsApiMock.outbound)).subscribe() - def act = ws.callRpc(new JsonRpcRequest("eth_getTransactionByHash", ["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"], 15, null, null, false)) + def act = ws.callRpc(new JsonRpcRequest("eth_getTransactionByHash", new ListParams(["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"]), 15, null, null, false)) then: StepVerifier.create(act) @@ -124,7 +125,7 @@ class WsConnectionImplSpec extends Specification { when: Flux.from(ws.handle(wsApiMock.inbound, wsApiMock.outbound)).subscribe() - def act = ws.callRpc(new JsonRpcRequest("eth_getTransactionByHash", ["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"], 15, null, null, false)) + def act = ws.callRpc(new JsonRpcRequest("eth_getTransactionByHash", new ListParams(["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"]), 15, null, null, false)) then: StepVerifier.create(act) diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImplSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImplSpec.groovy index 714f1726..e1011682 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImplSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/WsSubscriptionsImplSpec.groovy @@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.ethereum import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcWsMessage +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.publisher.Flux import reactor.core.publisher.Mono import spock.lang.Specification @@ -45,7 +46,7 @@ class WsSubscriptionsImplSpec extends Specification { def ws = new WsSubscriptionsImpl(pool) when: - def act = ws.subscribe(new JsonRpcRequest("eth_subscribe", ["foo_bar"])) + def act = ws.subscribe(new JsonRpcRequest("eth_subscribe", new ListParams(["foo_bar"]))) .data .map { new String(it) } .take(3) @@ -55,7 +56,7 @@ class WsSubscriptionsImplSpec extends Specification { act == ["100", "101", "102"] 1 * conn.callRpc({ JsonRpcRequest req -> - req.method == "eth_subscribe" && req.params == ["foo_bar"] + req.method == "eth_subscribe" && req.params == new ListParams(["foo_bar"]) }) >> Mono.just(new JsonRpcResponse('"0xcff45d00e7"'.bytes, null)) 1 * conn.getSubscribeResponses() >> answers } @@ -83,7 +84,7 @@ class WsSubscriptionsImplSpec extends Specification { def ws = new WsSubscriptionsImpl(pool) when: - def act = ws.subscribe(new JsonRpcRequest("eth_subscribe", ["foo_bar"])) + def act = ws.subscribe(new JsonRpcRequest("eth_subscribe", new ListParams(["foo_bar"]))) .data .map { new String(it) } .take(3) @@ -93,7 +94,7 @@ class WsSubscriptionsImplSpec extends Specification { act == ["100", "101", "102"] 1 * conn.callRpc({ JsonRpcRequest req -> - req.method == "eth_subscribe" && req.params == ["foo_bar"] + req.method == "eth_subscribe" && req.params == new ListParams(["foo_bar"]) }) >> Mono.just(new JsonRpcResponse('"0xcff45d00e7"'.bytes, null)) 1 * conn.getSubscribeResponses() >> answers } diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxesSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxesSpec.groovy index 6e6d73f7..36b2b595 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxesSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/subscribe/WebsocketPendingTxesSpec.groovy @@ -16,6 +16,7 @@ package io.emeraldpay.dshackle.upstream.ethereum.subscribe import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.ethereum.WsSubscriptions import reactor.core.publisher.Flux @@ -42,7 +43,7 @@ class WebsocketPendingTxesSpec extends Specification { .collectList().block(Duration.ofSeconds(1)) then: - 1 * ws.subscribe(new JsonRpcRequest("eth_subscribe", ["newPendingTransactions"])) >> new WsSubscriptions.SubscribeData( + 1 * ws.subscribe(new JsonRpcRequest("eth_subscribe", new ListParams(["newPendingTransactions"]))) >> new WsSubscriptions.SubscribeData( Flux.fromIterable(responses), "id", new AtomicReference("") ) txes.collect {it.toHex() } == [ diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClientSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClientSpec.groovy index 5b8a024d..7fb47bd5 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClientSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcGrpcClientSpec.groovy @@ -8,6 +8,7 @@ import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.test.MockGrpcServer import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.grpc.stub.StreamObserver import spock.lang.Specification @@ -39,7 +40,7 @@ class JsonRpcGrpcClientSpec extends Specification { when: def act = client.read( - new JsonRpcRequest("test", []) + new JsonRpcRequest("test", new ListParams()) ).block(Duration.ofSeconds(1)) then: @@ -73,7 +74,7 @@ class JsonRpcGrpcClientSpec extends Specification { when: client.read( - new JsonRpcRequest("test", []) + new JsonRpcRequest("test", new ListParams()) ).block(Duration.ofSeconds(1)) then: diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcHttpClientSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcHttpClientSpec.groovy index fa64ba4d..0ddd5d8a 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcHttpClientSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcHttpClientSpec.groovy @@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.upstream.rpcclient import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcResponseError +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import io.micrometer.core.instrument.Counter import io.micrometer.core.instrument.Timer import org.mockserver.integration.ClientAndServer @@ -61,7 +62,7 @@ class JsonRpcHttpClientSpec extends Specification { HttpResponse.response(resp) ) when: - def act = client.read(new JsonRpcRequest("test", [])).block() + def act = client.read(new JsonRpcRequest("test", new ListParams())).block() then: act.error == null new String(act.result) == '"0x98de45"' @@ -80,7 +81,7 @@ class JsonRpcHttpClientSpec extends Specification { ) when: def act = client.read( - new JsonRpcRequest("ping", []) + new JsonRpcRequest("ping", new ListParams()) ).block(Duration.ofSeconds(1)) then: def t = thrown(RuntimeException) // reactor.core.Exceptions$ReactiveException @@ -108,7 +109,7 @@ class JsonRpcHttpClientSpec extends Specification { ) when: def act = client.read( - new JsonRpcRequest("ping", []) + new JsonRpcRequest("ping", new ListParams()) ).block(Duration.ofSeconds(1)) then: def t = thrown(RuntimeException) // reactor.core.Exceptions$ReactiveException diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequestSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequestSpec.groovy index 393d9532..677d7544 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequestSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcRequestSpec.groovy @@ -17,12 +17,13 @@ package io.emeraldpay.dshackle.upstream.rpcclient import spock.lang.Specification +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams class JsonRpcRequestSpec extends Specification { def "Serialize empty params"() { setup: - def req = new JsonRpcRequest("test_foo", []) + def req = new JsonRpcRequest("test_foo", new ListParams()) when: def act = req.toJson() then: @@ -31,7 +32,7 @@ class JsonRpcRequestSpec extends Specification { def "Serialize single param"() { setup: - def req = new JsonRpcRequest("test_foo", ["0x0000"]) + def req = new JsonRpcRequest("test_foo", new ListParams(["0x0000"])) when: def act = req.toJson() then: @@ -40,7 +41,7 @@ class JsonRpcRequestSpec extends Specification { def "Serialize two params"() { setup: - def req = new JsonRpcRequest("test_foo", ["0x0000", false]) + def req = new JsonRpcRequest("test_foo", new ListParams(["0x0000", false])) when: def act = req.toJson() then: @@ -49,8 +50,8 @@ class JsonRpcRequestSpec extends Specification { def "Same requests are equal"() { setup: - def req1 = new JsonRpcRequest("test_foo", ["0x0000", false]) - def req2 = new JsonRpcRequest("test_foo", ["0x0000", false]) + def req1 = new JsonRpcRequest("test_foo", new ListParams(["0x0000", false])) + def req2 = new JsonRpcRequest("test_foo", new ListParams(["0x0000", false])) when: def act = req1.equals(req2) then: diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcWsClientSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcWsClientSpec.groovy index f5844b72..739ac7e0 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcWsClientSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/rpcclient/JsonRpcWsClientSpec.groovy @@ -2,6 +2,7 @@ package io.emeraldpay.dshackle.upstream.rpcclient import io.emeraldpay.dshackle.upstream.ethereum.WsConnection import io.emeraldpay.dshackle.upstream.ethereum.WsConnectionPool +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import reactor.core.Exceptions import spock.lang.Specification @@ -17,7 +18,7 @@ class JsonRpcWsClientSpec extends Specification { } def client = new JsonRpcWsClient(pool) when: - client.read(new JsonRpcRequest("foo_bar", [], 1)) + client.read(new JsonRpcRequest("foo_bar", new ListParams([]), 1)) .block(Duration.ofSeconds(1)) then: def t = thrown(Exceptions.ReactiveException) diff --git a/src/test/kotlin/io/emeraldpay/dshackle/upstream/RecursiveLowerBoundBlockDetectorTest.kt b/src/test/kotlin/io/emeraldpay/dshackle/upstream/RecursiveLowerBoundBlockDetectorTest.kt index 1b6e4b18..1f194713 100644 --- a/src/test/kotlin/io/emeraldpay/dshackle/upstream/RecursiveLowerBoundBlockDetectorTest.kt +++ b/src/test/kotlin/io/emeraldpay/dshackle/upstream/RecursiveLowerBoundBlockDetectorTest.kt @@ -6,6 +6,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.EthereumLowerBoundBlockDetector import io.emeraldpay.dshackle.upstream.polkadot.PolkadotLowerBoundBlockDetector import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments @@ -87,11 +88,11 @@ class RecursiveLowerBoundBlockDetectorTest { blocks.forEach { if (it == 17964844L) { on { - read(JsonRpcRequest("eth_getBalance", listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", it.toHex()))) + read(JsonRpcRequest("eth_getBalance", ListParams("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", it.toHex()))) } doReturn Mono.just(JsonRpcResponse(ByteArray(0), null)) } else { on { - read(JsonRpcRequest("eth_getBalance", listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", it.toHex()))) + read(JsonRpcRequest("eth_getBalance", ListParams("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", it.toHex()))) } doReturn Mono.error(RuntimeException("missing trie node")) } } @@ -103,17 +104,17 @@ class RecursiveLowerBoundBlockDetectorTest { blocks.forEach { if (it == 17964844L) { on { - read(JsonRpcRequest("chain_getBlockHash", listOf(it.toHex()))) + read(JsonRpcRequest("chain_getBlockHash", ListParams(it.toHex()))) } doReturn Mono.just(JsonRpcResponse("\"$hash1\"".toByteArray(), null)) on { - read(JsonRpcRequest("state_getMetadata", listOf(hash1))) + read(JsonRpcRequest("state_getMetadata", ListParams(hash1))) } doReturn Mono.just(JsonRpcResponse(ByteArray(0), null)) } else { on { - read(JsonRpcRequest("chain_getBlockHash", listOf(it.toHex()))) + read(JsonRpcRequest("chain_getBlockHash", ListParams(it.toHex()))) } doReturn Mono.just(JsonRpcResponse("\"$hash2\"".toByteArray(), null)) on { - read(JsonRpcRequest("state_getMetadata", listOf(hash2))) + read(JsonRpcRequest("state_getMetadata", ListParams(hash2))) } doReturn Mono.error(RuntimeException("State already discarded for")) } } diff --git a/src/test/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetectorTest.kt b/src/test/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetectorTest.kt index 49605f6a..70015896 100644 --- a/src/test/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetectorTest.kt +++ b/src/test/kotlin/io/emeraldpay/dshackle/upstream/solana/SolanaLowerBoundBlockDetectorTest.kt @@ -6,6 +6,7 @@ import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.mockito.kotlin.doReturn @@ -19,13 +20,13 @@ class SolanaLowerBoundBlockDetectorTest { @Test fun `get solana lower block and slot`() { val reader = mock { - on { read(JsonRpcRequest("getFirstAvailableBlock", listOf())) } doReturn + on { read(JsonRpcRequest("getFirstAvailableBlock", ListParams())) } doReturn Mono.just(JsonRpcResponse("25000000".toByteArray(), null)) on { read( JsonRpcRequest( "getBlock", - listOf( + ListParams( 25000000L, mapOf( "showRewards" to false,