Fix archive detection (#310)
This commit is contained in:
@@ -1,11 +1,16 @@
|
|||||||
package io.emeraldpay.dshackle.upstream.ethereum
|
package io.emeraldpay.dshackle.upstream.ethereum
|
||||||
|
|
||||||
|
import io.emeraldpay.dshackle.Chain
|
||||||
import io.emeraldpay.dshackle.reader.JsonRpcReader
|
import io.emeraldpay.dshackle.reader.JsonRpcReader
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||||
import io.emeraldpay.etherjar.hex.HexQuantity
|
import io.emeraldpay.etherjar.hex.HexQuantity
|
||||||
import reactor.core.publisher.Mono
|
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(
|
class EthereumArchiveBlockNumberReader(
|
||||||
private val reader: JsonRpcReader,
|
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
|
String(it).substring(3, it.size - 1).toLong(radix = 16) - 10_000, // this is definitely archive
|
||||||
).toHex()
|
).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) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ open class EthereumLikeRpcUpstream(
|
|||||||
) : EthereumLikeUpstream(id, hash, options, role, targets, node, chainConfig), Lifecycle, Upstream, CachesEnabled {
|
) : EthereumLikeUpstream(id, hash, options, role, targets, node, chainConfig), Lifecycle, Upstream, CachesEnabled {
|
||||||
private val validator: EthereumUpstreamValidator = EthereumUpstreamValidator(chain, this, getOptions(), chainConfig.callLimitContract)
|
private val validator: EthereumUpstreamValidator = EthereumUpstreamValidator(chain, this, getOptions(), chainConfig.callLimitContract)
|
||||||
protected val connector: EthereumConnector = connectorFactory.create(this, validator, chain, skipEnhance)
|
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 hasLiveSubscriptionHead: AtomicBoolean = AtomicBoolean(false)
|
||||||
|
|
||||||
private var validatorSubscription: Disposable? = null
|
private var validatorSubscription: Disposable? = null
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package io.emeraldpay.dshackle.upstream.ethereum.subscribe
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import io.emeraldpay.dshackle.Chain
|
||||||
import io.emeraldpay.dshackle.Global.Companion.objectMapper
|
import io.emeraldpay.dshackle.Global.Companion.objectMapper
|
||||||
import io.emeraldpay.dshackle.reader.JsonRpcReader
|
import io.emeraldpay.dshackle.reader.JsonRpcReader
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumArchiveBlockNumberReader
|
import io.emeraldpay.dshackle.upstream.ethereum.EthereumArchiveBlockNumberReader
|
||||||
@@ -12,7 +13,9 @@ import reactor.core.publisher.Mono
|
|||||||
|
|
||||||
class EthereumLabelsDetector(
|
class EthereumLabelsDetector(
|
||||||
private val reader: JsonRpcReader,
|
private val reader: JsonRpcReader,
|
||||||
|
private val chain: Chain,
|
||||||
) {
|
) {
|
||||||
|
private val blockNumberReader = EthereumArchiveBlockNumberReader(reader)
|
||||||
|
|
||||||
fun detectLabels(): Flux<Pair<String, String>> {
|
fun detectLabels(): Flux<Pair<String, String>> {
|
||||||
return Flux.merge(
|
return Flux.merge(
|
||||||
@@ -39,21 +42,23 @@ class EthereumLabelsDetector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun detectArchiveNode(): Mono<Pair<String, String>> {
|
private fun detectArchiveNode(): Mono<Pair<String, String>> {
|
||||||
return EthereumArchiveBlockNumberReader(reader)
|
return Mono.zip(
|
||||||
.readArchiveBlock()
|
blockNumberReader.readEarliestBlock(chain).flatMap { haveBalance(it) },
|
||||||
.flatMap {
|
blockNumberReader.readArchiveBlock().flatMap { haveBalance(it) },
|
||||||
reader.read(
|
)
|
||||||
JsonRpcRequest(
|
|
||||||
"eth_getBalance",
|
|
||||||
listOf("0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", it),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.flatMap(JsonRpcResponse::requireResult)
|
|
||||||
.map { "archive" to "true" }
|
.map { "archive" to "true" }
|
||||||
.onErrorResume { Mono.empty() }
|
.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? {
|
private fun nodeType(nodeType: String): String? {
|
||||||
return if (nodeType.contains("erigon", true)) {
|
return if (nodeType.contains("erigon", true)) {
|
||||||
"erigon"
|
"erigon"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.emeraldpay.dshackle.upstream.ethereum
|
package io.emeraldpay.dshackle.upstream.ethereum
|
||||||
|
|
||||||
|
import io.emeraldpay.dshackle.Chain
|
||||||
import io.emeraldpay.dshackle.reader.Reader
|
import io.emeraldpay.dshackle.reader.Reader
|
||||||
import io.emeraldpay.dshackle.test.ApiReaderMock
|
import io.emeraldpay.dshackle.test.ApiReaderMock
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
import io.emeraldpay.dshackle.test.TestingCommons
|
||||||
@@ -23,9 +24,10 @@ class EthereumLabelsDetectorSpec extends Specification {
|
|||||||
answer("web3_clientVersion", [], response)
|
answer("web3_clientVersion", [], response)
|
||||||
answer("eth_blockNumber", [], "0x10df3e5")
|
answer("eth_blockNumber", [], "0x10df3e5")
|
||||||
answer("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"], "")
|
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:
|
when:
|
||||||
def act = detector.detectLabels()
|
def act = detector.detectLabels()
|
||||||
@@ -55,9 +57,11 @@ class EthereumLabelsDetectorSpec extends Specification {
|
|||||||
Mono.just(new JsonRpcResponse("\"0x10df3e5\"".getBytes(), null))
|
Mono.just(new JsonRpcResponse("\"0x10df3e5\"".getBytes(), null))
|
||||||
1 * read(new JsonRpcRequest("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"])) >>
|
1 * read(new JsonRpcRequest("eth_getBalance", ["0x756F45E3FA69347A9A973A725E3C98bC4db0b5a0", "0x10dccd5"])) >>
|
||||||
Mono.error(new RuntimeException())
|
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:
|
when:
|
||||||
def act = detector.detectLabels()
|
def act = detector.detectLabels()
|
||||||
then:
|
then:
|
||||||
|
|||||||
Reference in New Issue
Block a user