From 208deb55a150e19fae3e18b9098f6c99c843f2ed Mon Sep 17 00:00:00 2001 From: KirillPamPam Date: Mon, 2 Oct 2023 15:34:48 +0400 Subject: [PATCH] Fix archive detection (#310) --- .../EthereumArchiveBlockNumberReader.kt | 13 +++++++++ .../ethereum/EthereumLikeRpcUpstream.kt | 2 +- .../subscribe/EthereumLabelsDetector.kt | 27 +++++++++++-------- .../EthereumLabelsDetectorSpec.groovy | 8 ++++-- 4 files changed, 36 insertions(+), 14 deletions(-) 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 ff446495..294887d3 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumArchiveBlockNumberReader.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumArchiveBlockNumberReader.kt @@ -1,11 +1,16 @@ package io.emeraldpay.dshackle.upstream.ethereum +import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.etherjar.hex.HexQuantity import reactor.core.publisher.Mono +private const val ARBITRUM_NITRO_BLOCK = "0x152DD47" // 22207815 +private const val OPTIMISM_BEDROCK_BLOCK = "0x645C277" // 105235063 +private const val EARLIEST_BLOCK = "0x2710" // 10000 + class EthereumArchiveBlockNumberReader( private val reader: JsonRpcReader, ) { @@ -19,4 +24,12 @@ class EthereumArchiveBlockNumberReader( String(it).substring(3, it.size - 1).toLong(radix = 16) - 10_000, // this is definitely archive ).toHex() } + + fun readEarliestBlock(chain: Chain): Mono { + return when (chain) { + Chain.ARBITRUM__MAINNET -> ARBITRUM_NITRO_BLOCK + Chain.OPTIMISM__MAINNET -> OPTIMISM_BEDROCK_BLOCK + else -> EARLIEST_BLOCK + }.run { Mono.just(this) } + } } diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt index c6aefc7a..a2f001a4 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/ethereum/EthereumLikeRpcUpstream.kt @@ -53,7 +53,7 @@ open class EthereumLikeRpcUpstream( ) : EthereumLikeUpstream(id, hash, options, role, targets, node, chainConfig), Lifecycle, Upstream, CachesEnabled { private val validator: EthereumUpstreamValidator = EthereumUpstreamValidator(chain, this, getOptions(), chainConfig.callLimitContract) protected val connector: EthereumConnector = connectorFactory.create(this, validator, chain, skipEnhance) - private val labelsDetector = EthereumLabelsDetector(this.getIngressReader()) + private val labelsDetector = EthereumLabelsDetector(this.getIngressReader(), chain) private var hasLiveSubscriptionHead: AtomicBoolean = AtomicBoolean(false) private var validatorSubscription: Disposable? = null 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 8155dba1..9bf33c49 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 @@ -2,6 +2,7 @@ package io.emeraldpay.dshackle.upstream.ethereum.subscribe import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.readValue +import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Global.Companion.objectMapper import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.upstream.ethereum.EthereumArchiveBlockNumberReader @@ -12,7 +13,9 @@ import reactor.core.publisher.Mono class EthereumLabelsDetector( private val reader: JsonRpcReader, + private val chain: Chain, ) { + private val blockNumberReader = EthereumArchiveBlockNumberReader(reader) fun detectLabels(): Flux> { return Flux.merge( @@ -39,21 +42,23 @@ class EthereumLabelsDetector( } private fun detectArchiveNode(): Mono> { - return EthereumArchiveBlockNumberReader(reader) - .readArchiveBlock() - .flatMap { - reader.read( - JsonRpcRequest( - "eth_getBalance", - listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", it), - ), - ) - } - .flatMap(JsonRpcResponse::requireResult) + return Mono.zip( + blockNumberReader.readEarliestBlock(chain).flatMap { haveBalance(it) }, + blockNumberReader.readArchiveBlock().flatMap { haveBalance(it) }, + ) .map { "archive" to "true" } .onErrorResume { Mono.empty() } } + private fun haveBalance(blockNumber: String): Mono { + return reader.read( + JsonRpcRequest( + "eth_getBalance", + listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", blockNumber), + ), + ).flatMap(JsonRpcResponse::requireResult) + } + private fun nodeType(nodeType: String): String? { return if (nodeType.contains("erigon", true)) { "erigon" 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 41705455..728366f4 100644 --- a/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy +++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/ethereum/EthereumLabelsDetectorSpec.groovy @@ -1,5 +1,6 @@ package io.emeraldpay.dshackle.upstream.ethereum +import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.test.ApiReaderMock import io.emeraldpay.dshackle.test.TestingCommons @@ -23,9 +24,10 @@ class EthereumLabelsDetectorSpec extends Specification { answer("web3_clientVersion", [], response) answer("eth_blockNumber", [], "0x10df3e5") answer("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"], "") + answer("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x2710"], "") } ) - def detector = new EthereumLabelsDetector(up.getIngressReader()) + def detector = new EthereumLabelsDetector(up.getIngressReader(), Chain.ETHEREUM__MAINNET) when: def act = detector.detectLabels() @@ -55,9 +57,11 @@ class EthereumLabelsDetectorSpec extends Specification { Mono.just(new JsonRpcResponse("\"0x10df3e5\"".getBytes(), null)) 1 * read(new JsonRpcRequest("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"])) >> Mono.error(new RuntimeException()) + 1 * read(new JsonRpcRequest("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x2710"])) >> + Mono.just(new JsonRpcResponse("".getBytes(), null)) } } - def detector = new EthereumLabelsDetector(up.getIngressReader()) + def detector = new EthereumLabelsDetector(up.getIngressReader(), Chain.ETHEREUM__MAINNET) when: def act = detector.detectLabels() then: