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