From 03383cf1b5f3391cad7506b51e59f640fbf7d897 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 12 May 2025 16:35:51 +0300 Subject: [PATCH] Add starknet node version detector (#663) * Add starknet node version detector * add juno version detecting --- .../starknet/StarknetChainSpecific.kt | 8 ++ .../StarknetUpstreamSettingsDetector.kt | 75 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetUpstreamSettingsDetector.kt 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 3d75f92b..88fbefcc 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetChainSpecific.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetChainSpecific.kt @@ -14,6 +14,7 @@ import io.emeraldpay.dshackle.upstream.GenericSingleCallValidator import io.emeraldpay.dshackle.upstream.SingleValidator import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.UpstreamAvailability +import io.emeraldpay.dshackle.upstream.UpstreamSettingsDetector import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundService @@ -107,6 +108,13 @@ object StarknetChainSpecific : AbstractPollChainSpecific() { override fun latestBlockRequest(): ChainRequest = ChainRequest("starknet_getBlockWithTxHashes", ListParams("latest")) + + override fun upstreamSettingsDetector( + chain: Chain, + upstream: Upstream, + ): UpstreamSettingsDetector { + return StarknetUpstreamSettingsDetector(upstream, chain) + } } @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetUpstreamSettingsDetector.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetUpstreamSettingsDetector.kt new file mode 100644 index 00000000..b7750912 --- /dev/null +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/starknet/StarknetUpstreamSettingsDetector.kt @@ -0,0 +1,75 @@ +package io.emeraldpay.dshackle.upstream.starknet + +import io.emeraldpay.dshackle.Chain +import io.emeraldpay.dshackle.upstream.ChainRequest +import io.emeraldpay.dshackle.upstream.ChainResponse +import io.emeraldpay.dshackle.upstream.Upstream +import io.emeraldpay.dshackle.upstream.UpstreamSettingsDetector +import io.emeraldpay.dshackle.upstream.rpcclient.ListParams +import reactor.core.publisher.Flux + +class StarknetUpstreamSettingsDetector( + private val upstream: Upstream, + private val chain: Chain, +) : UpstreamSettingsDetector(upstream) { + override fun internalDetectLabels(): Flux> { + return Flux.merge( + detectNodeType(), + ) + } + + private fun detectNodeType(): Flux?> { + return upstream + .getIngressReader() + .read(pathfinderVersionRequest()) + .flatMap(ChainResponse::requireResult) + .flatMapMany { data -> + val version = parseClientVersion(data) + if (version.isEmpty()) { + throw Exception() + } + val labels = + mutableListOf("client_type" to "pathfinder", "client_version" to version) + Flux.fromIterable(labels) + }.onErrorResume { + upstream + .getIngressReader() + .read(clientVersionRequest()) + .flatMap(ChainResponse::requireResult) + .flatMapMany { data -> + val version = parseClientVersion(data) + if (version.isEmpty()) { + throw Exception() + } + val labels = + mutableListOf( + "client_type" to "juno", + "client_version" to version, + ) + Flux.fromIterable(labels) + } + .onErrorResume { error -> + log.warn( + "Can't detect the node type of upstream ${upstream.getId()}, reason - {}", + error.message, + ) + Flux.empty() + } + } + } + + override fun clientVersionRequest(): ChainRequest = ChainRequest("juno_version", ListParams()) + + private fun pathfinderVersionRequest() = ChainRequest("pathfinder_version", ListParams()) + + override fun parseClientVersion(data: ByteArray): String { + var version = String(data) + if (version.startsWith("\"") && version.endsWith("\"")) { + version = version.substring(1, version.length - 1) + } + if (version.startsWith("v")) { + version = version.substring(1, version.length) + } + return version + } +}