Logs lower bound + fix state detection with null (#503)

This commit is contained in:
KirillPamPam
2024-06-11 14:13:18 +04:00
committed by GitHub
parent ba3f3aa338
commit f9667e2f60
11 changed files with 122 additions and 12 deletions

View File

@@ -97,6 +97,7 @@ class StreamHead(
LowerBoundType.STATE -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_STATE
LowerBoundType.BLOCK -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOCK
LowerBoundType.TX -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_TX
LowerBoundType.LOGS -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_LOGS
}
}

View File

@@ -15,7 +15,12 @@ import reactor.core.publisher.Mono
class EthereumLowerBoundBlockDetector(
private val upstream: Upstream,
) : LowerBoundDetector() {
private val recursiveLowerBound = RecursiveLowerBound(upstream, LowerBoundType.BLOCK, setOf("No block data"), lowerBounds)
companion object {
private const val NO_BLOCK_DATA = "No block data"
}
private val recursiveLowerBound = RecursiveLowerBound(upstream, LowerBoundType.BLOCK, setOf(NO_BLOCK_DATA), lowerBounds)
override fun period(): Long {
return 3
@@ -35,7 +40,7 @@ class EthereumLowerBoundBlockDetector(
)
.doOnNext {
if (it.hasResult() && it.getResult().contentEquals("null".toByteArray())) {
throw IllegalStateException("No block data")
throw IllegalStateException(NO_BLOCK_DATA)
}
}
}

View File

@@ -0,0 +1,53 @@
package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.upstream.ChainRequest
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundData
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundDetector
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundType
import io.emeraldpay.dshackle.upstream.lowerbound.detector.RecursiveLowerBound
import io.emeraldpay.dshackle.upstream.lowerbound.toHex
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
import reactor.core.publisher.Flux
class EthereumLowerBoundLogsDetector(
private val upstream: Upstream,
) : LowerBoundDetector() {
companion object {
const val MAX_OFFSET = 20
private const val NO_LOGS_DATA = "No logs data"
}
private val recursiveLowerBound = RecursiveLowerBound(upstream, LowerBoundType.LOGS, setOf(NO_LOGS_DATA), lowerBounds)
override fun period(): Long {
return 3
}
override fun internalDetectLowerBound(): Flux<LowerBoundData> {
return recursiveLowerBound.recursiveDetectLowerBoundWithOffset(MAX_OFFSET) { block ->
upstream.getIngressReader()
.read(
ChainRequest(
"eth_getLogs",
ListParams(
mapOf(
"fromBlock" to block.toHex(),
"toBlock" to block.toHex(),
),
),
),
)
.doOnNext {
if (it.hasResult() && (it.getResult().contentEquals("null".toByteArray()) || it.getResult().contentEquals("[]".toByteArray()))) {
throw IllegalStateException(NO_LOGS_DATA)
}
}
}
}
override fun types(): Set<LowerBoundType> {
return setOf(LowerBoundType.LOGS)
}
}

View File

@@ -14,6 +14,7 @@ class EthereumLowerBoundService(
EthereumLowerBoundStateDetector(upstream),
EthereumLowerBoundBlockDetector(upstream),
EthereumLowerBoundTxDetector(upstream),
EthereumLowerBoundLogsDetector(upstream),
)
}
}

View File

@@ -1,5 +1,6 @@
package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.upstream.ChainRequest
import io.emeraldpay.dshackle.upstream.ChainResponse
import io.emeraldpay.dshackle.upstream.Upstream
@@ -41,6 +42,7 @@ class EthereumLowerBoundStateDetector(
"historical backend error", // optimism
"load state tree: failed to load state tree", // filecoin
"purged for block", // erigon
"No state data", // our own error if there is "null" in response
)
}
@@ -59,6 +61,10 @@ class EthereumLowerBoundStateDetector(
ListParams(ZERO_ADDRESS, block.toHex()),
),
)
}.doOnNext {
if (it.hasResult() && it.getResult().contentEquals(Global.nullValue)) {
throw IllegalStateException("No state data")
}
}
}
}

View File

@@ -10,12 +10,16 @@ import io.emeraldpay.dshackle.upstream.lowerbound.toHex
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
import reactor.core.publisher.Flux
const val MAX_OFFSET = 20
class EthereumLowerBoundTxDetector(
private val upstream: Upstream,
) : LowerBoundDetector() {
private val recursiveLowerBound = RecursiveLowerBound(upstream, LowerBoundType.TX, setOf("No tx data"), lowerBounds)
companion object {
const val MAX_OFFSET = 20
private const val NO_TX_DATA = "No tx data"
}
private val recursiveLowerBound = RecursiveLowerBound(upstream, LowerBoundType.TX, setOf(NO_TX_DATA), lowerBounds)
override fun period(): Long {
return 3
@@ -32,7 +36,7 @@ class EthereumLowerBoundTxDetector(
)
.doOnNext {
if (it.hasResult() && (it.getResult().contentEquals("null".toByteArray()) || it.getResultAsProcessedString().substring(2).toLong(16) == 0L)) {
throw IllegalStateException("No tx data")
throw IllegalStateException(NO_TX_DATA)
}
}
}

View File

@@ -2,6 +2,7 @@ package io.emeraldpay.dshackle.upstream.ethereum
import com.fasterxml.jackson.databind.JsonNode
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.upstream.BasicEthUpstreamSettingsDetector
import io.emeraldpay.dshackle.upstream.ChainRequest
import io.emeraldpay.dshackle.upstream.ChainResponse
@@ -60,7 +61,13 @@ class EthereumUpstreamSettingsDetector(
"eth_getBalance",
ListParams(ZERO_ADDRESS, blockNumber),
),
).flatMap(ChainResponse::requireResult)
)
.flatMap(ChainResponse::requireResult)
.doOnNext {
if (it.contentEquals(Global.nullValue)) {
throw IllegalStateException("Null data")
}
}
}
override fun nodeTypeRequest(): NodeTypeRequest = NodeTypeRequest(clientVersionRequest())

View File

@@ -20,7 +20,7 @@ data class LowerBoundData(
}
enum class LowerBoundType {
UNKNOWN, STATE, SLOT, BLOCK, TX
UNKNOWN, STATE, SLOT, BLOCK, TX, LOGS
}
fun BlockchainOuterClass.LowerBoundType.fromProtoType(): LowerBoundType {
@@ -31,5 +31,6 @@ fun BlockchainOuterClass.LowerBoundType.fromProtoType(): LowerBoundType {
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOCK -> LowerBoundType.BLOCK
BlockchainOuterClass.LowerBoundType.UNRECOGNIZED -> LowerBoundType.UNKNOWN
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_TX -> LowerBoundType.TX
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_LOGS -> LowerBoundType.LOGS
}
}