Skip to content

Commit

Permalink
Fix archive detection (#310)
Browse files Browse the repository at this point in the history
  • Loading branch information
KirillPamPam authored Oct 2, 2023
1 parent 3875ec2 commit 208deb5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -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,
) {
Expand All @@ -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<String> {
return when (chain) {
Chain.ARBITRUM__MAINNET -> ARBITRUM_NITRO_BLOCK
Chain.OPTIMISM__MAINNET -> OPTIMISM_BEDROCK_BLOCK
else -> EARLIEST_BLOCK
}.run { Mono.just(this) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Pair<String, String>> {
return Flux.merge(
Expand All @@ -39,21 +42,23 @@ class EthereumLabelsDetector(
}

private fun detectArchiveNode(): Mono<Pair<String, String>> {
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<ByteArray> {
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"
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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()
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit 208deb5

Please sign in to comment.