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:
@@ -18,10 +18,16 @@ abstract class UpstreamRpcMethodsDetector(
|
|||||||
listOf(
|
listOf(
|
||||||
"method ([A-Za-z0-9_]+) does not exist/is not available",
|
"method ([A-Za-z0-9_]+) does not exist/is not available",
|
||||||
"([A-Za-z0-9_]+) found but the containing module is disabled",
|
"([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",
|
"The method ([A-Za-z0-9_]+) is not available",
|
||||||
).map { s -> s.toRegex() }
|
).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())
|
open fun detectRpcMethods(): Mono<Map<String, Boolean>> = detectByMagicMethod().switchIfEmpty(detectByMethod())
|
||||||
|
|
||||||
protected fun detectByMethod(): Mono<Map<String, Boolean>> =
|
protected fun detectByMethod(): Mono<Map<String, Boolean>> =
|
||||||
@@ -38,9 +44,15 @@ abstract class UpstreamRpcMethodsDetector(
|
|||||||
method to true
|
method to true
|
||||||
}
|
}
|
||||||
.onErrorResume { err ->
|
.onErrorResume { err ->
|
||||||
val notAvailableError =
|
val methodAvailableError =
|
||||||
|
availableRegexps.any { s -> s.containsMatchIn(err.message ?: "") }
|
||||||
|
val methodNotAvailableError =
|
||||||
notAvailableRegexps.any { s -> s.containsMatchIn(err.message ?: "") }
|
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")
|
log.error("$method failed with ${err.message}, detect as false")
|
||||||
Mono.just(method to false)
|
Mono.just(method to false)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class BasicEthUpstreamRpcMethodsDetector(
|
|||||||
setOf(
|
setOf(
|
||||||
"eth_getBlockReceipts" to ListParams("latest"),
|
"eth_getBlockReceipts" to ListParams("latest"),
|
||||||
"trace_callMany" to ListParams(listOf(listOf<Any>())),
|
"trace_callMany" to ListParams(listOf(listOf<Any>())),
|
||||||
|
"eth_simulateV1" to ListParams(listOf(listOf<Any>())),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun parseRpcModules(data: ByteArray): Map<String, Boolean> {
|
private fun parseRpcModules(data: ByteArray): Map<String, Boolean> {
|
||||||
|
|||||||
@@ -48,6 +48,15 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
|
|||||||
null,
|
null,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
on {
|
||||||
|
read(ChainRequest("eth_simulateV1", ListParams(listOf(listOf<Any>()))))
|
||||||
|
} doReturn
|
||||||
|
Mono.just(
|
||||||
|
ChainResponse(
|
||||||
|
"[]".toByteArray(),
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val upstream =
|
val upstream =
|
||||||
@@ -97,6 +106,15 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
|
|||||||
null,
|
null,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
on {
|
||||||
|
read(ChainRequest("eth_simulateV1", ListParams(listOf(listOf<Any>()))))
|
||||||
|
} doReturn
|
||||||
|
Mono.just(
|
||||||
|
ChainResponse(
|
||||||
|
"[]".toByteArray(),
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val upstream =
|
val upstream =
|
||||||
@@ -108,7 +126,7 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
|
|||||||
val detector = BasicEthUpstreamRpcMethodsDetector(upstream, config)
|
val detector = BasicEthUpstreamRpcMethodsDetector(upstream, config)
|
||||||
Assertions.assertThat(detector.detectRpcMethods().block()).apply {
|
Assertions.assertThat(detector.detectRpcMethods().block()).apply {
|
||||||
isNotNull()
|
isNotNull()
|
||||||
hasSize(2)
|
hasSize(3)
|
||||||
containsEntry("eth_getBlockReceipts", true)
|
containsEntry("eth_getBlockReceipts", true)
|
||||||
containsEntry("trace_callMany", true)
|
containsEntry("trace_callMany", true)
|
||||||
}
|
}
|
||||||
@@ -147,6 +165,15 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
|
|||||||
null,
|
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 =
|
val upstream =
|
||||||
@@ -168,6 +195,7 @@ class BasicEthUpstreamRpcMethodsDetectorTest {
|
|||||||
containsEntry("eth_getBlockByNumber", false)
|
containsEntry("eth_getBlockByNumber", false)
|
||||||
containsEntry("eth_getBlockReceipts", true)
|
containsEntry("eth_getBlockReceipts", true)
|
||||||
containsEntry("debug_traceBlock", true)
|
containsEntry("debug_traceBlock", true)
|
||||||
|
containsEntry("eth_simulateV1", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user