support eth_simulateV1 for all EVM node types (#645)

* support eth_simulateV1 for all EVM node types

* eth_simulateV1 detector

* eth_simulateV1 rewrite detector with special error

* eth_simulateV1 add invalid params error as valid

* build fix

* fix eth_simulateV1 detector behavior

* detect as true log message

---------

Co-authored-by: Andrey Bronin <bronin@iMac.local>
This commit is contained in:
Andrey Bronin
2025-04-02 12:12:10 +03:00
committed by GitHub
parent a79d64c066
commit c0a9f80478
3 changed files with 45 additions and 4 deletions

View File

@@ -18,10 +18,16 @@ abstract class UpstreamRpcMethodsDetector(
listOf(
"method ([A-Za-z0-9_]+) does not exist/is not available",
"([A-Za-z0-9_]+) found but the containing module is disabled",
"Method not found",
"[Mm]ethod not found",
"The method ([A-Za-z0-9_]+) is not available",
).map { s -> s.toRegex() }
private val availableRegexps =
listOf(
"missing value for required argument ([0-9]+)",
"Invalid params",
).map { s -> s.toRegex() }
open fun detectRpcMethods(): Mono<Map<String, Boolean>> = detectByMagicMethod().switchIfEmpty(detectByMethod())
protected fun detectByMethod(): Mono<Map<String, Boolean>> =
@@ -38,9 +44,15 @@ abstract class UpstreamRpcMethodsDetector(
method to true
}
.onErrorResume { err ->
val notAvailableError =
val methodAvailableError =
availableRegexps.any { s -> s.containsMatchIn(err.message ?: "") }
val methodNotAvailableError =
notAvailableRegexps.any { s -> s.containsMatchIn(err.message ?: "") }
if (notAvailableError) {
if (methodAvailableError) {
log.error("$method failed with ${err.message}, detect as true")
Mono.just(method to true)
} else if (methodNotAvailableError) {
log.error("$method failed with ${err.message}, detect as false")
Mono.just(method to false)
} else {

View File

@@ -34,6 +34,7 @@ class BasicEthUpstreamRpcMethodsDetector(
setOf(
"eth_getBlockReceipts" to ListParams("latest"),
"trace_callMany" to ListParams(listOf(listOf<Any>())),
"eth_simulateV1" to ListParams(listOf(listOf<Any>())),
)
private fun parseRpcModules(data: ByteArray): Map<String, Boolean> {

View File

@@ -48,6 +48,15 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
null,
),
)
on {
read(ChainRequest("eth_simulateV1", ListParams(listOf(listOf<Any>()))))
} doReturn
Mono.just(
ChainResponse(
"[]".toByteArray(),
null,
),
)
}
val upstream =
@@ -97,6 +106,15 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
null,
),
)
on {
read(ChainRequest("eth_simulateV1", ListParams(listOf(listOf<Any>()))))
} doReturn
Mono.just(
ChainResponse(
"[]".toByteArray(),
null,
),
)
}
val upstream =
@@ -108,7 +126,7 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
val detector = BasicEthUpstreamRpcMethodsDetector(upstream, config)
Assertions.assertThat(detector.detectRpcMethods().block()).apply {
isNotNull()
hasSize(2)
hasSize(3)
containsEntry("eth_getBlockReceipts", true)
containsEntry("trace_callMany", true)
}
@@ -147,6 +165,15 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
null,
),
)
on {
read(ChainRequest("eth_simulateV1", ListParams(listOf(listOf<Any>()))))
} doReturn
Mono.just(
ChainResponse(
null,
ChainCallError(32602, "missing value for required argument 0"),
),
)
}
val upstream =
@@ -168,6 +195,7 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
containsEntry("eth_getBlockByNumber", false)
containsEntry("eth_getBlockReceipts", true)
containsEntry("debug_traceBlock", true)
containsEntry("eth_simulateV1", true)
}
}
}