diff --git a/build.gradle b/build.gradle index a86ab019..63b5af2a 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.70' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30' classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' } } @@ -297,5 +297,5 @@ jacocoTestReport { } } jacoco { - toolVersion = "0.8.5" + toolVersion = "0.8.7" } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 21843ddb..0af9ca7d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Languages groovyVersion=2.5.14 -kotlinVersion=1.3.11 +kotlinVersion=1.5.30 protocVersion=3.9.0 # Main Libs slf4jVersion=1.7.25 diff --git a/src/main/kotlin/io/emeraldpay/dshackle/cache/BlocksRedisCache.kt b/src/main/kotlin/io/emeraldpay/dshackle/cache/BlocksRedisCache.kt index 4c823029..7bf3de73 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/cache/BlocksRedisCache.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/cache/BlocksRedisCache.kt @@ -73,7 +73,7 @@ class BlocksRedisCache( } fun add(block: BlockContainer): Mono { - if (block.timestamp == null || block.hash == null) { + if (block.timestamp == null || block.hash == null) { //null in unit tests return Mono.empty() } if (block.full) { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/cache/Caches.kt b/src/main/kotlin/io/emeraldpay/dshackle/cache/Caches.kt index 98fe40ef..8aac7b85 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/cache/Caches.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/cache/Caches.kt @@ -115,7 +115,7 @@ open class Caches( //for LATEST data cache it in memory, it may be short living so better to avoid Redis memoizeBlock(block) } else if (tag == Tag.REQUESTED) { - var blockOnlyContainer: BlockContainer? = null + val blockOnlyContainer: BlockContainer? var jsonValue: BlockJson<*>? = null if (block.full) { jsonValue = Global.objectMapper.readValue>(block.json, BlockJson::class.java) @@ -130,8 +130,8 @@ open class Caches( redisBlocksByHash?.add(blockOnlyContainer)?.let(job::add) // now cache only transactions - jsonValue?.let { jsonValue -> - val plainTransactions = jsonValue.transactions.filterIsInstance() + jsonValue?.let { value -> + val plainTransactions = value.transactions.filterIsInstance() if (plainTransactions.isNotEmpty()) { val transactions = plainTransactions.map { tx -> TxContainer.from(tx) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/cache/HeightByHashRedisCache.kt b/src/main/kotlin/io/emeraldpay/dshackle/cache/HeightByHashRedisCache.kt index 17f1ce09..535ef3b9 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/cache/HeightByHashRedisCache.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/cache/HeightByHashRedisCache.kt @@ -42,6 +42,7 @@ class HeightByHashRedisCache( private const val MAX_CACHE_TIME_MINUTES = 60L * 4 } + @Suppress("UNCHECKED_CAST") override fun read(key: BlockId): Mono { return redis.get(key(key)) .flatMap { data -> @@ -54,13 +55,13 @@ class HeightByHashRedisCache( override fun add(block: BlockContainer): Mono { return Mono.just(block) - .flatMap { block -> + .flatMap { blockData -> // even if block replaced, the mapping hash-long is still valid, so can be cached for long time // even for fresh blocks val ttl = TimeUnit.MINUTES.toSeconds(MAX_CACHE_TIME_MINUTES) - val key = key(block.hash) - val value = asBytes(block.height) + val key = key(blockData.hash) + val value = asBytes(blockData.height) redis.setex(key, ttl, value) } .doOnError { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/cache/OnBlockRedisCache.kt b/src/main/kotlin/io/emeraldpay/dshackle/cache/OnBlockRedisCache.kt index dd735d99..b733fdb7 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/cache/OnBlockRedisCache.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/cache/OnBlockRedisCache.kt @@ -90,10 +90,10 @@ abstract class OnBlockRedisCache( * Add to cache. * Note that it returns Mono which must be subscribed to actually save */ - open fun add(block: BlockContainer, value: T): Mono { - return Mono.just(block) + open fun add(container: BlockContainer, value: T): Mono { + return Mono.just(container) .flatMap { block -> - val ttl = cachingTime(block.timestamp!!) + val ttl = cachingTime(block.timestamp) if (ttl > MIN_CACHE_TIME_SECONDS) { val key = key(block.hash) val proto = toProto(block, value) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/cache/OnTxRedisCache.kt b/src/main/kotlin/io/emeraldpay/dshackle/cache/OnTxRedisCache.kt index 74ff6a56..e8f2a711 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/cache/OnTxRedisCache.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/cache/OnTxRedisCache.kt @@ -59,8 +59,8 @@ abstract class OnTxRedisCache( return "${prefix}:${chain.id}:${hash.toHex()}" } - fun evict(block: BlockContainer): Mono { - return Mono.just(block) + fun evict(container: BlockContainer): Mono { + return Mono.just(container) .map { block -> block.transactions.map { key(it) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/config/AuthConfigReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/config/AuthConfigReader.kt index a5af0d97..cc36f2ef 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/config/AuthConfigReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/config/AuthConfigReader.kt @@ -60,24 +60,24 @@ class AuthConfigReader : YamlConfigReader() { * ca: "ca.dshackle.test.crt" * ``` */ - fun readServerTls(node: MappingNode?): AuthConfig.ServerTlsAuth? { - return getMapping(node, "tls")?.let { node -> + fun readServerTls(rootNode: MappingNode?): AuthConfig.ServerTlsAuth? { + return getMapping(rootNode, "tls")?.let { tlsNode -> val auth = AuthConfig.ServerTlsAuth() - getValueAsBool(node, "enabled")?.let { + getValueAsBool(tlsNode, "enabled")?.let { auth.enabled = it } if (auth.enabled != null && !auth.enabled!!) { return null } - getMapping(node, "server")?.let { node -> - auth.certificate = getValueAsString(node, "certificate") - auth.key = getValueAsString(node, "key") + getMapping(tlsNode, "server")?.let { serverNode -> + auth.certificate = getValueAsString(serverNode, "certificate") + auth.key = getValueAsString(serverNode, "key") } - getMapping(node, "client")?.let { node -> - getValueAsBool(node, "require")?.let { + getMapping(tlsNode, "client")?.let { clientNode -> + getValueAsBool(clientNode, "require")?.let { auth.clientRequire = it } - auth.clientCa = getValueAsString(node, "ca") + auth.clientCa = getValueAsString(clientNode, "ca") } auth } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/config/CacheConfigReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/config/CacheConfigReader.kt index 38a40ab6..40c65d15 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/config/CacheConfigReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/config/CacheConfigReader.kt @@ -33,20 +33,20 @@ class CacheConfigReader : YamlConfigReader(), ConfigReader { override fun read(input: MappingNode?): CacheConfig? { return getMapping(input, "cache")?.let { node -> val config = CacheConfig() - getMapping(node, "redis")?.let { node -> + getMapping(node, "redis")?.let { redisNode -> val redis = CacheConfig.Redis() - val enabled = getValueAsBool(node, "enabled") ?: true + val enabled = getValueAsBool(redisNode, "enabled") ?: true if (enabled) { - getValueAsString(node, "host")?.let { + getValueAsString(redisNode, "host")?.let { redis.host = it } - getValueAsInt(node, "port")?.let { + getValueAsInt(redisNode, "port")?.let { redis.port = it } - getValueAsInt(node, "db")?.let { + getValueAsInt(redisNode, "db")?.let { redis.db = it } - getValueAsString(node, "password")?.let { + getValueAsString(redisNode, "password")?.let { redis.password = it } config.redis = redis diff --git a/src/main/kotlin/io/emeraldpay/dshackle/config/TokensConfigReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/config/TokensConfigReader.kt index 70bdbb38..169f7ffe 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/config/TokensConfigReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/config/TokensConfigReader.kt @@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.config import org.slf4j.LoggerFactory import org.yaml.snakeyaml.nodes.MappingNode import java.io.InputStream +import java.util.* class TokensConfigReader : YamlConfigReader(), ConfigReader { @@ -38,7 +39,7 @@ class TokensConfigReader : YamlConfigReader(), ConfigReader { token.address = getValueAsString(node, "address") token.name = getValueAsString(node, "name") token.type = getValueAsString(node, "type")?.let { - if (it.toUpperCase() == "ERC-20") { + if (it.uppercase(Locale.getDefault()) == "ERC-20") { TokensConfig.Type.ERC20 } else { log.warn("Invalid token type: $it") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfig.kt b/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfig.kt index a2c19b99..d0038558 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfig.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfig.kt @@ -78,7 +78,7 @@ open class UpstreamsConfig { var methods: Methods? = null var role: UpstreamRole = UpstreamRole.STANDARD - @Suppress("unchecked") + @Suppress("UNCHECKED_CAST") fun cast(type: Class): Upstream { if (connection == null || type.isAssignableFrom(connection!!.javaClass)) { return this as Upstream @@ -144,20 +144,19 @@ open class UpstreamsConfig { DSHACKLE("dshackle", "grpc"), UNKNOWN("unknown"); - private val code: Array + private val code: Array init { - this.code = code as Array + this.code = code Arrays.sort(this.code) } companion object { fun byName(code: String): UpstreamType { - var code = code - code = code.toLowerCase() + val cleanCode = code.lowercase(Locale.getDefault()) for (t in UpstreamType.values()) { - if (Arrays.binarySearch(t.code, code) >= 0) { + if (Arrays.binarySearch(t.code, cleanCode) >= 0) { return t } } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfigReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfigReader.kt index 3e683e5d..b9f42934 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfigReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/config/UpstreamsConfigReader.kt @@ -26,6 +26,8 @@ import java.io.InputStream import java.lang.IllegalArgumentException import java.net.URI import java.time.Duration +import java.util.* +import kotlin.collections.ArrayList class UpstreamsConfigReader( private val fileResolver: FileResolver @@ -83,7 +85,7 @@ class UpstreamsConfigReader( } } - getList(input, "upstreams")?.value?.forEachIndexed { pos, upNode -> + getList(input, "upstreams")?.value?.forEachIndexed { _, upNode -> val connNode = getMapping(upNode, "connection") if (hasAny(connNode, "ethereum")) { val connConfigNode = getMapping(connNode, "ethereum")!! @@ -197,7 +199,7 @@ class UpstreamsConfigReader( getValueAsString(upNode, "role")?.let { val name = it.trim() try { - val role = UpstreamsConfig.UpstreamRole.valueOf(name.toUpperCase()) + val role = UpstreamsConfig.UpstreamRole.valueOf(name.uppercase(Locale.getDefault())) upstream.role = role } catch (e: IllegalArgumentException) { log.warn("Unsupported role `$name` for upstream ${upstream.id}") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/config/YamlConfigReader.kt b/src/main/kotlin/io/emeraldpay/dshackle/config/YamlConfigReader.kt index 62f520b9..fcd432e8 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/config/YamlConfigReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/config/YamlConfigReader.kt @@ -24,6 +24,7 @@ import org.yaml.snakeyaml.nodes.Node import org.yaml.snakeyaml.nodes.ScalarNode import java.io.InputStream import java.io.InputStreamReader +import java.util.* abstract class YamlConfigReader { private val envVariables = EnvVariables() @@ -50,6 +51,7 @@ abstract class YamlConfigReader { }.count() > 0 } + @Suppress("UNCHECKED_CAST") private fun getValue(mappingNode: MappingNode?, key: String, type: Class): T? { if (mappingNode == null) { return null @@ -79,6 +81,7 @@ abstract class YamlConfigReader { return getValue(mappingNode, key, ScalarNode::class.java) } + @Suppress("UNCHECKED_CAST") protected fun getList(mappingNode: MappingNode?, key: String): CollectionNode? { val value = getValue(mappingNode, key, CollectionNode::class.java) ?: return null return value as CollectionNode @@ -109,7 +112,7 @@ abstract class YamlConfigReader { protected fun getValueAsBool(mappingNode: MappingNode?, key: String): Boolean? { return getValue(mappingNode, key)?.let { return@let if (it.isPlain) { - it.value?.toLowerCase() == "true" + it.value.lowercase(Locale.getDefault()) == "true" } else { null } @@ -128,8 +131,8 @@ abstract class YamlConfigReader { fun getBlockchain(id: String): Chain { return Chain.values().find { chain -> - chain.name == id.toUpperCase() - || chain.chainCode.toUpperCase() == id.toUpperCase() + chain.name == id.uppercase(Locale.getDefault()) + || chain.chainCode.uppercase(Locale.getDefault()) == id.uppercase(Locale.getDefault()) || chain.id.toString() == id } ?: Chain.UNSPECIFIED } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/data/SourceContainer.kt b/src/main/kotlin/io/emeraldpay/dshackle/data/SourceContainer.kt index 1dc82c61..eeb27ad4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/data/SourceContainer.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/data/SourceContainer.kt @@ -23,6 +23,7 @@ abstract class SourceContainer( private val parsed: Any? ) { + @Suppress("UNCHECKED_CAST") fun getParsed(clazz: Class): T? { if (parsed == null) { return null diff --git a/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/AccessLogWriter.kt b/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/AccessLogWriter.kt index 3573952d..64ef6017 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/AccessLogWriter.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/AccessLogWriter.kt @@ -103,7 +103,7 @@ class AccessLogWriter( BufferedOutputStream(FileOutputStream(filename, true)).use { wrt -> var limit = WRITE_BATCH_LIMIT while (limit > 0) { - limit-- + limit -= 1 val next = queue.poll() ?: return val bytes: ByteArray? = try { objectMapper.writeValueAsBytes(next) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/EventsBuilder.kt b/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/EventsBuilder.kt index cf1be6d3..25ad3a8f 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/EventsBuilder.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/monitoring/accesslog/EventsBuilder.kt @@ -195,7 +195,7 @@ class EventsBuilder { override fun onRequest(msg: BlockchainOuterClass.BalanceRequest) { balanceRequest = Events.BalanceRequest( - msg.asset.code.toUpperCase(), + msg.asset.code.uppercase(Locale.getDefault()), msg.address.addrTypeCase.name ) } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/proxy/ProxyServer.kt b/src/main/kotlin/io/emeraldpay/dshackle/proxy/ProxyServer.kt index c997aca9..753b70b4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/proxy/ProxyServer.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/proxy/ProxyServer.kt @@ -111,7 +111,7 @@ class ProxyServer( serverBuilder = serverBuilder.secure { secure -> secure.sslContext(sslContext) } } - val server: DisposableServer = serverBuilder + serverBuilder .route(this::setupRoutes) .bindNow() } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/proxy/ReadRpcJson.kt b/src/main/kotlin/io/emeraldpay/dshackle/proxy/ReadRpcJson.kt index da46e095..78edd6cf 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/proxy/ReadRpcJson.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/proxy/ReadRpcJson.kt @@ -101,9 +101,9 @@ open class ReadRpcJson() : Function { } catch (e: IllegalArgumentException) { throw RpcException(RpcResponseError.CODE_INVALID_JSON, "Empty JSON") } - if (first == '{'.toByte()) { + if (first == '{'.code.toByte()) { return ProxyCall.RpcType.SINGLE - } else if (first == '['.toByte()) { + } else if (first == '['.code.toByte()) { return ProxyCall.RpcType.BATCH } throw RpcException(RpcResponseError.CODE_INVALID_JSON, "Failed to parse JSON") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/quorum/QuorumReaderFactory.kt b/src/main/kotlin/io/emeraldpay/dshackle/quorum/QuorumReaderFactory.kt index 4d3ecfdb..8e0727bb 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/quorum/QuorumReaderFactory.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/quorum/QuorumReaderFactory.kt @@ -20,7 +20,7 @@ import io.emeraldpay.dshackle.upstream.ApiSource import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest // creates instance of a Quorum based reader -open interface QuorumReaderFactory { +interface QuorumReaderFactory { companion object { fun default(): QuorumReaderFactory { @@ -28,7 +28,7 @@ open interface QuorumReaderFactory { } } - open fun create(apis: ApiSource, quorum: CallQuorum): Reader + fun create(apis: ApiSource, quorum: CallQuorum): Reader class Default : QuorumReaderFactory { override fun create(apis: ApiSource, quorum: CallQuorum): Reader { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/BlockchainRpc.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/BlockchainRpc.kt index 364c06eb..ea122fd2 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/BlockchainRpc.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/BlockchainRpc.kt @@ -33,8 +33,6 @@ import reactor.core.publisher.Flux import reactor.core.publisher.Mono import java.util.* import java.util.concurrent.TimeUnit -import java.util.concurrent.locks.ReentrantLock -import kotlin.concurrent.withLock @Service @DependsOn("monitoringSetup") class BlockchainRpc( @@ -82,8 +80,8 @@ class BlockchainRpc( ).doOnError { errorMetric.increment() } } - override fun subscribeTxStatus(request: Mono): Flux { - return request.flatMapMany { request -> + override fun subscribeTxStatus(requestMono: Mono): Flux { + return requestMono.flatMapMany { request -> val chain = Chain.byId(request.chainValue) val metrics = chainMetrics.get(chain) metrics.subscribeTxMetric.increment() @@ -106,7 +104,7 @@ class BlockchainRpc( val chain = Chain.byId(request.asset.chainValue) val metrics = chainMetrics.get(chain) metrics.subscribeBalanceMetric.increment() - val asset = request.asset.code.toLowerCase() + val asset = request.asset.code.lowercase(Locale.getDefault()) try { trackAddress.find { it.isSupported(chain, asset) }?.let { track -> track.subscribe(request) @@ -129,7 +127,7 @@ class BlockchainRpc( val chain = Chain.byId(request.asset.chainValue) val metrics = chainMetrics.get(chain) metrics.getBalanceMetric.increment() - val asset = request.asset.code.toLowerCase() + val asset = request.asset.code.lowercase(Locale.getDefault()) val startTime = System.currentTimeMillis() try { trackAddress.find { it.isSupported(chain, asset) }?.let { track -> diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt index 70854fc9..88146d51 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt @@ -153,7 +153,7 @@ open class NativeCall( .forMethod(method) .forLabels(Selector.convertToMatcher(request.selector)) - val callQuorum = upstream.getMethods().getQuorumFor(method) ?: AlwaysQuorum() + val callQuorum = upstream.getMethods().getQuorumFor(method) ?: AlwaysQuorum() // can be null in tests callQuorum.init(upstream.getHead()) // for NotLaggingQuorum it makes sense to select compatible upstreams before the call @@ -218,6 +218,7 @@ open class NativeCall( ) } + @Suppress("UNCHECKED_CAST") private fun extractParams(jsonParams: String): List { if (StringUtils.isEmpty(jsonParams)) { return emptyList() diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackBitcoinAddress.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackBitcoinAddress.kt index 798ab7f7..13aaea5d 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackBitcoinAddress.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackBitcoinAddress.kt @@ -220,7 +220,7 @@ class TrackBitcoinAddress( if (isBalanceAvailable(chain)) { val addresses = allAddresses(upstream, request).cache() val following = upstream.getHead().getFlux() - .flatMap { block -> + .flatMap { requestBalances(chain, upstream, Flux.from(addresses), request.includeUtxo) } val last = HashMap() diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackERC20Address.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackERC20Address.kt index d29f0d2c..4cf53f4f 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackERC20Address.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackERC20Address.kt @@ -22,7 +22,9 @@ import org.springframework.stereotype.Service import reactor.core.publisher.Flux import reactor.core.publisher.Mono import java.math.BigInteger +import java.util.* import javax.annotation.PostConstruct +import kotlin.collections.HashMap @Service class TrackERC20Address( @@ -41,7 +43,7 @@ class TrackERC20Address( fun init() { tokensConfig.tokens.forEach { token -> val chain = token.blockchain!! - val asset = token.name!!.toLowerCase() + val asset = token.name!!.lowercase(Locale.getDefault()) val id = TokenId(chain, asset) val definition = TokenDefinition( chain, asset, @@ -53,13 +55,13 @@ class TrackERC20Address( } override fun isSupported(chain: Chain, asset: String): Boolean { - return tokens.containsKey(TokenId(chain, asset.toLowerCase())) && + return tokens.containsKey(TokenId(chain, asset.lowercase(Locale.getDefault()))) && BlockchainType.from(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain) } override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux { val chain = Chain.byId(request.asset.chainValue) - val asset = request.asset.code.toLowerCase() + val asset = request.asset.code.lowercase(Locale.getDefault()) val tokenDefinition = tokens[TokenId(chain, asset)] ?: return Flux.empty() return ethereumAddresses.extract(request.address) .map { TrackedAddress(chain, it, tokenDefinition.token, tokenDefinition.name) } @@ -69,7 +71,7 @@ class TrackERC20Address( override fun subscribe(request: BlockchainOuterClass.BalanceRequest): Flux { val chain = Chain.byId(request.asset.chainValue) - val asset = request.asset.code.toLowerCase() + val asset = request.asset.code.lowercase(Locale.getDefault()) val tokenDefinition = tokens[TokenId(chain, asset)] ?: return Flux.empty() val head = multistreamHolder.getUpstream(chain)?.getHead()?.getFlux() ?: Flux.empty() @@ -116,7 +118,7 @@ class TrackERC20Address( .setBalance(address.balance!!.toString(10)) .setAsset(Common.Asset.newBuilder() .setChainValue(address.chain.id) - .setCode(address.tokenName.toUpperCase())) + .setCode(address.tokenName.uppercase(Locale.getDefault()))) .setAddress(Common.SingleAddress.newBuilder().setAddress(address.address.toHex())) .build() } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackEthereumAddress.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackEthereumAddress.kt index db78f4e4..5d641f46 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackEthereumAddress.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/TrackEthereumAddress.kt @@ -31,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import reactor.core.publisher.Flux import reactor.core.publisher.Mono +import java.util.* @Service class TrackEthereumAddress( @@ -98,7 +99,7 @@ class TrackEthereumAddress( if (!multistreamHolder.isAvailable(chain)) { return Flux.error(SilentException.UnsupportedBlockchain(request.asset.chainValue)) } - if (request.asset.code?.toLowerCase() != "ether") { + if (request.asset.code.lowercase(Locale.getDefault()) != "ether") { return Flux.error(SilentException("Unsupported asset ${request.asset.code}")) } return ethereumAddresses.extract(request.address).map { diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Multistream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Multistream.kt index 0b5e1244..f1816dd5 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Multistream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Multistream.kt @@ -36,6 +36,7 @@ import reactor.core.publisher.Mono import reactor.core.scheduler.Schedulers import java.time.Duration import java.time.Instant +import java.util.* import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.locks.ReentrantLock import java.util.function.Predicate @@ -70,7 +71,7 @@ abstract class Multistream( init { UpstreamAvailability.values().forEach { status -> Metrics.gauge("$metrics.availability", - listOf(Tag.of("chain", chain.chainCode), Tag.of("status", status.name.toLowerCase())), this) { + listOf(Tag.of("chain", chain.chainCode), Tag.of("status", status.name.lowercase(Locale.getDefault()))), this) { upstreams.count { it.getStatus() == status }.toDouble() } } @@ -187,7 +188,7 @@ abstract class Multistream( override fun getStatus(): UpstreamAvailability { val upstreams = getAll() return if (upstreams.isEmpty()) UpstreamAvailability.UNAVAILABLE - else upstreams.map { it.getStatus() }.min()!! + else upstreams.minOf { it.getStatus() } } //TODO options for multistream are useless diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt index 13780476..8a0fdafc 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/Selector.kt @@ -119,6 +119,7 @@ class Selector { return Collections.unmodifiableCollection(matchers) } + @Suppress("UNCHECKED_CAST") fun getMatcher(type: Class): T? { return matchers.find { type.isAssignableFrom(it.javaClass) } as T? } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt index f845729f..fc7e44d4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinMultistream.kt @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory import org.springframework.context.Lifecycle import reactor.core.publisher.Mono +@Suppress("UNCHECKED_CAST") open class BitcoinMultistream( chain: Chain, val upstreams: MutableList, @@ -108,6 +109,7 @@ open class BitcoinMultistream( return upstreams.flatMap { it.getLabels() } } + @Suppress("UNCHECKED_CAST") override fun cast(selfType: Class): T { if (!selfType.isAssignableFrom(this.javaClass)) { throw ClassCastException("Cannot cast ${this.javaClass} to $selfType") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcUpstream.kt index f3b5ef87..2f5d8c23 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/BitcoinRpcUpstream.kt @@ -78,6 +78,7 @@ open class BitcoinRpcUpstream( return false } + @Suppress("UNCHECKED_CAST") override fun cast(selfType: Class): T { if (!selfType.isAssignableFrom(this.javaClass)) { throw ClassCastException("Cannot cast ${this.javaClass} to $selfType") 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 a22fa9c7..ec18ac72 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/CachingMempoolData.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/CachingMempoolData.kt @@ -62,6 +62,7 @@ open class CachingMempoolData( } } + @Suppress("UNCHECKED_CAST") fun fetchFromUpstream(): Mono> { return upstreams.getDirectApi(Selector.empty).flatMap { api -> api.read(JsonRpcRequest("getrawmempool", emptyList())) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/ExtractBlock.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/ExtractBlock.kt index dfdeb421..cb87fea0 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/ExtractBlock.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/bitcoin/ExtractBlock.kt @@ -51,6 +51,7 @@ class ExtractBlock() { private val objectMapper: ObjectMapper = Global.objectMapper + @Suppress("UNCHECKED_CAST") fun extract(json: ByteArray): BlockContainer { val data = objectMapper.readValue(json, Map::class.java) as Map 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 6905aaab..fe2daa70 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumDirectReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumDirectReader.kt @@ -45,7 +45,7 @@ class EthereumDirectReader( } private val objectMapper: ObjectMapper = Global.objectMapper - open var quorumReaderFactory: QuorumReaderFactory = QuorumReaderFactory.default() + var quorumReaderFactory: QuorumReaderFactory = QuorumReaderFactory.default() val blockReader: Reader val blockByHeightReader: Reader @@ -110,6 +110,7 @@ class EthereumDirectReader( } } + @Suppress("UNCHECKED_CAST") private fun readBlock(request: JsonRpcRequest, id: String): Mono { return readWithQuorum(request) .timeout(Defaults.timeoutInternal, Mono.error(TimeoutException("Block not read $id"))) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt index 4efc6fec..963aac5c 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumMultistream.kt @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory import org.springframework.context.Lifecycle import reactor.core.publisher.Mono +@Suppress("UNCHECKED_CAST") open class EthereumMultistream( chain: Chain, val upstreams: MutableList, @@ -109,7 +110,7 @@ open class EthereumMultistream( return upstreams.flatMap { it.getLabels() } } - @SuppressWarnings("unchecked") + @Suppress("UNCHECKED_CAST") override fun cast(selfType: Class): T { if (!selfType.isAssignableFrom(this.javaClass)) { throw ClassCastException("Cannot cast ${this.javaClass} to $selfType") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumRpcUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumRpcUpstream.kt index 3258a9e6..1e0a9600 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumRpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumRpcUpstream.kt @@ -120,7 +120,7 @@ open class EthereumRpcUpstream( return false } - @Suppress("unchecked") + @Suppress("UNCHECKED_CAST") override fun cast(selfType: Class): T { if (!selfType.isAssignableFrom(this.javaClass)) { throw ClassCastException("Cannot cast ${this.javaClass} to $selfType") 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 0922bcf9..72406b8a 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/BitcoinGrpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/BitcoinGrpcUpstream.kt @@ -111,6 +111,7 @@ class BitcoinGrpcUpstream( return true } + @Suppress("UNCHECKED_CAST") override fun cast(selfType: Class): T { if (!selfType.isAssignableFrom(this.javaClass)) { throw ClassCastException("Cannot cast ${this.javaClass} to $selfType") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/EthereumGrpcUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/EthereumGrpcUpstream.kt index daee77f8..700d91f8 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/EthereumGrpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/EthereumGrpcUpstream.kt @@ -142,7 +142,7 @@ open class EthereumGrpcUpstream( return defaultReader } - @SuppressWarnings("unchecked") + @Suppress("UNCHECKED_CAST") override fun cast(selfType: Class): T { if (!selfType.isAssignableFrom(this.javaClass)) { throw ClassCastException("Cannot cast ${this.javaClass} to $selfType") diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/GrpcUpstreams.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/GrpcUpstreams.kt index a609799a..572311cd 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/GrpcUpstreams.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/grpc/GrpcUpstreams.kt @@ -83,7 +83,7 @@ class GrpcUpstreams( val updates = Flux.interval(Duration.ZERO, Duration.ofMinutes(1)) .flatMap { client.describe(BlockchainOuterClass.DescribeRequest.newBuilder().build()) - }.onErrorContinue { t, u -> + }.onErrorContinue { t, _ -> if (ExceptionUtils.indexOfType(t, ConnectException::class.java) >= 0) { log.warn("gRPC upstream $host:$port is unavailable") known.values.forEach {