@@ -12,8 +12,28 @@ abstract class EthereumLowerBoundErrorHandler : ErrorHandler {
|
||||
override fun handle(upstream: Upstream, request: ChainRequest, errorMessage: String?) {
|
||||
try {
|
||||
if (canHandle(request, errorMessage)) {
|
||||
parseTagParam(request, tagIndex(request.method))?.let {
|
||||
upstream.updateLowerBound(it, type())
|
||||
parseTagParam(request, tagIndex(request.method))?.let { parsed ->
|
||||
val currentHeight = upstream.getHead().getCurrentHeight()
|
||||
if (currentHeight == null) {
|
||||
log.warn(
|
||||
"Skip {} lower bound update for {}: head height unknown (parsed={})",
|
||||
type(),
|
||||
upstream.getId(),
|
||||
parsed,
|
||||
)
|
||||
return@let
|
||||
}
|
||||
if (parsed > currentHeight) {
|
||||
log.warn(
|
||||
"Skip {} lower bound update for {}: parsed tag {} exceeds head {}",
|
||||
type(),
|
||||
upstream.getId(),
|
||||
parsed,
|
||||
currentHeight,
|
||||
)
|
||||
return@let
|
||||
}
|
||||
upstream.updateLowerBound(parsed, type())
|
||||
}
|
||||
}
|
||||
} catch (e: RuntimeException) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.emeraldpay.dshackle.upstream.error
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.ChainRequest
|
||||
import io.emeraldpay.dshackle.upstream.Head
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundType
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
||||
@@ -10,17 +11,18 @@ import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.Arguments.of
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import org.mockito.Mockito.anyLong
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.never
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class EthereumStateLowerBoundErrorHandlerTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requests")
|
||||
fun `update lower bound`(request: ChainRequest) {
|
||||
val upstream = mock<Upstream>()
|
||||
val upstream = mockUpstreamWithHead(300_000_000L)
|
||||
val handler = EthereumStateLowerBoundErrorHandler
|
||||
|
||||
handler.handle(upstream, request, "missing trie node d5648cc9aef48154159d53800f2f")
|
||||
@@ -28,6 +30,53 @@ class EthereumStateLowerBoundErrorHandlerTest {
|
||||
verify(upstream).updateLowerBound(213229736, LowerBoundType.STATE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no update lower bound if parsed tag exceeds head`() {
|
||||
val upstream = mockUpstreamWithHead(100_000_000L)
|
||||
|
||||
EthereumStateLowerBoundErrorHandler.handle(
|
||||
upstream,
|
||||
ChainRequest("eth_getBalance", ListParams("0x343", "0xCB5A0A8")),
|
||||
"missing trie node d5648cc9aef48154159d53800f2f",
|
||||
)
|
||||
|
||||
verify(upstream, never()).updateLowerBound(anyLong(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no update lower bound if head height is null`() {
|
||||
val upstream = mockUpstreamWithHead(null)
|
||||
|
||||
EthereumStateLowerBoundErrorHandler.handle(
|
||||
upstream,
|
||||
ChainRequest("eth_getBalance", ListParams("0x343", "0xCB5A0A8")),
|
||||
"missing trie node d5648cc9aef48154159d53800f2f",
|
||||
)
|
||||
|
||||
verify(upstream, never()).updateLowerBound(anyLong(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no update lower bound for the Base prod incident value`() {
|
||||
val upstream = mockUpstreamWithHead(30_000_000L)
|
||||
|
||||
EthereumStateLowerBoundErrorHandler.handle(
|
||||
upstream,
|
||||
ChainRequest("eth_getBalance", ListParams("0x343", "0xD150C7F1")),
|
||||
"missing trie node d5648cc9aef48154159d53800f2f",
|
||||
)
|
||||
|
||||
verify(upstream, never()).updateLowerBound(anyLong(), any())
|
||||
}
|
||||
|
||||
private fun mockUpstreamWithHead(height: Long?): Upstream {
|
||||
val head = mock<Head>()
|
||||
whenever(head.getCurrentHeight()).thenReturn(height)
|
||||
val upstream = mock<Upstream>()
|
||||
whenever(upstream.getHead()).thenReturn(head)
|
||||
return upstream
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no update lower bound if error is not about state`() {
|
||||
val upstream = mock<Upstream>()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.emeraldpay.dshackle.upstream.error
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.ChainRequest
|
||||
import io.emeraldpay.dshackle.upstream.Head
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundType
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
||||
@@ -9,15 +10,19 @@ import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.Arguments
|
||||
import org.junit.jupiter.params.provider.Arguments.of
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.anyLong
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.never
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class EthereumTraceLowerBoundErrorHandlerTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requests")
|
||||
fun `update lower bound`(request: ChainRequest) {
|
||||
val upstream = mock<Upstream>()
|
||||
val upstream = mockUpstreamWithHead(300_000_000L)
|
||||
val handler = EthereumTraceLowerBoundErrorHandler
|
||||
|
||||
handler.handle(upstream, request, "missing trie node d5648cc9aef48154159d53800f2f")
|
||||
@@ -27,7 +32,7 @@ class EthereumTraceLowerBoundErrorHandlerTest {
|
||||
|
||||
@Test
|
||||
fun `update lower bound base on regexp`() {
|
||||
val upstream = mock<Upstream>()
|
||||
val upstream = mockUpstreamWithHead(300_000_000L)
|
||||
val handler = EthereumTraceLowerBoundErrorHandler
|
||||
|
||||
handler.handle(upstream, ChainRequest("trace_block", ListParams("0xCB5A0A8")), "block #1 not found")
|
||||
@@ -35,6 +40,40 @@ class EthereumTraceLowerBoundErrorHandlerTest {
|
||||
verify(upstream).updateLowerBound(213229736, LowerBoundType.TRACE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no update lower bound if parsed tag exceeds head`() {
|
||||
val upstream = mockUpstreamWithHead(100_000_000L)
|
||||
|
||||
EthereumTraceLowerBoundErrorHandler.handle(
|
||||
upstream,
|
||||
ChainRequest("trace_block", ListParams("0xCB5A0A8")),
|
||||
"missing trie node d5648cc9aef48154159d53800f2f",
|
||||
)
|
||||
|
||||
verify(upstream, never()).updateLowerBound(anyLong(), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no update lower bound if head height is null`() {
|
||||
val upstream = mockUpstreamWithHead(null)
|
||||
|
||||
EthereumTraceLowerBoundErrorHandler.handle(
|
||||
upstream,
|
||||
ChainRequest("trace_block", ListParams("0xCB5A0A8")),
|
||||
"missing trie node d5648cc9aef48154159d53800f2f",
|
||||
)
|
||||
|
||||
verify(upstream, never()).updateLowerBound(anyLong(), any())
|
||||
}
|
||||
|
||||
private fun mockUpstreamWithHead(height: Long?): Upstream {
|
||||
val head = mock<Head>()
|
||||
whenever(head.getCurrentHeight()).thenReturn(height)
|
||||
val upstream = mock<Upstream>()
|
||||
whenever(upstream.getHead()).thenReturn(head)
|
||||
return upstream
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun requests(): List<Arguments> =
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
package io.emeraldpay.dshackle.upstream.error
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.ChainRequest
|
||||
import io.emeraldpay.dshackle.upstream.Head
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundType
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class UpstreamErrorHandlerTest {
|
||||
|
||||
@Test
|
||||
fun `use lower bound error handler`() {
|
||||
val head = mock<Head>()
|
||||
whenever(head.getCurrentHeight()).thenReturn(300_000_000L)
|
||||
val upstream = mock<Upstream>()
|
||||
whenever(upstream.getHead()).thenReturn(head)
|
||||
val request = ChainRequest("eth_getCode", ListParams("0x343", "0xCB5A0A8"))
|
||||
val handler = UpstreamErrorHandler
|
||||
|
||||
|
||||
Reference in New Issue
Block a user