lower bound detector for receipts (#674)
* lower bound detector for receipts * Add more non-retryable errors to dshackle proof detection
This commit is contained in:
Submodule emerald-grpc updated: 3b46c590db...6ca43f4dc2
@@ -150,6 +150,7 @@ class ChainEventMapper {
|
|||||||
LowerBoundType.PROOF -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_PROOF
|
LowerBoundType.PROOF -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_PROOF
|
||||||
LowerBoundType.BLOB -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOB
|
LowerBoundType.BLOB -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOB
|
||||||
LowerBoundType.EPOCH -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_EPOCH
|
LowerBoundType.EPOCH -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_EPOCH
|
||||||
|
LowerBoundType.RECEIPTS -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_RECEIPTS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ class StreamHead(
|
|||||||
LowerBoundType.PROOF -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_PROOF
|
LowerBoundType.PROOF -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_PROOF
|
||||||
LowerBoundType.BLOB -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOB
|
LowerBoundType.BLOB -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOB
|
||||||
LowerBoundType.EPOCH -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_EPOCH
|
LowerBoundType.EPOCH -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_EPOCH
|
||||||
|
LowerBoundType.RECEIPTS -> BlockchainOuterClass.LowerBoundType.LOWER_BOUND_RECEIPTS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class EthereumLowerBoundProofDetector(
|
|||||||
"proofs are available only for the 'latest' block",
|
"proofs are available only for the 'latest' block",
|
||||||
"missing trie node",
|
"missing trie node",
|
||||||
"cannot find EVM IAVL store",
|
"cannot find EVM IAVL store",
|
||||||
|
"old data not available due to pruning",
|
||||||
|
"no historical RPC is available",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package io.emeraldpay.dshackle.upstream.ethereum
|
||||||
|
|
||||||
|
import io.emeraldpay.dshackle.Defaults
|
||||||
|
import io.emeraldpay.dshackle.data.BlockContainer
|
||||||
|
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 EthereumLowerBoundReceiptsDetector(
|
||||||
|
private val upstream: Upstream,
|
||||||
|
) : LowerBoundDetector(upstream.getChain()) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MAX_OFFSET = 20
|
||||||
|
private const val NO_RECEIPTS_DATA = "No receipts data"
|
||||||
|
|
||||||
|
private val NO_RECEIPTS_ERRORS = setOf(
|
||||||
|
NO_RECEIPTS_DATA,
|
||||||
|
"block not found with number",
|
||||||
|
"requested epoch was a null round",
|
||||||
|
"missing trie node",
|
||||||
|
"old data not available due to pruning",
|
||||||
|
).plus(EthereumLowerBoundBlockDetector.NO_BLOCK_ERRORS)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val recursiveLowerBound = RecursiveLowerBound(upstream, LowerBoundType.RECEIPTS, NO_RECEIPTS_ERRORS, lowerBounds)
|
||||||
|
|
||||||
|
override fun period(): Long {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun internalDetectLowerBound(): Flux<LowerBoundData> {
|
||||||
|
return recursiveLowerBound.recursiveDetectLowerBoundWithOffset(MAX_OFFSET) { block ->
|
||||||
|
upstream.getIngressReader()
|
||||||
|
.read(
|
||||||
|
ChainRequest("eth_getBlockByNumber", ListParams(block.toHex(), false)),
|
||||||
|
)
|
||||||
|
.timeout(Defaults.internalCallsTimeout)
|
||||||
|
.doOnNext {
|
||||||
|
if (it.hasResult() && it.getResult().contentEquals("null".toByteArray())) {
|
||||||
|
throw IllegalStateException(NO_RECEIPTS_DATA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.handle { it, sink ->
|
||||||
|
val blockJson = BlockContainer.fromEthereumJson(it.getResult(), upstream.getId())
|
||||||
|
if (blockJson.transactions.isEmpty()) {
|
||||||
|
sink.error(IllegalStateException(NO_RECEIPTS_DATA))
|
||||||
|
return@handle
|
||||||
|
}
|
||||||
|
sink.next(blockJson.transactions[0].toHexWithPrefix())
|
||||||
|
}
|
||||||
|
.flatMap { tx ->
|
||||||
|
upstream.getIngressReader()
|
||||||
|
.read(
|
||||||
|
ChainRequest("eth_getTransactionReceipt", ListParams(tx)),
|
||||||
|
)
|
||||||
|
.timeout(Defaults.internalCallsTimeout)
|
||||||
|
.doOnNext {
|
||||||
|
if (it.hasResult() && it.getResult().contentEquals("null".toByteArray())) {
|
||||||
|
throw IllegalStateException(NO_RECEIPTS_DATA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun types(): Set<LowerBoundType> {
|
||||||
|
return setOf(LowerBoundType.RECEIPTS)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ class EthereumLowerBoundService(
|
|||||||
EthereumLowerBoundBlockDetector(upstream),
|
EthereumLowerBoundBlockDetector(upstream),
|
||||||
EthereumLowerBoundTxDetector(upstream),
|
EthereumLowerBoundTxDetector(upstream),
|
||||||
EthereumLowerBoundProofDetector(upstream),
|
EthereumLowerBoundProofDetector(upstream),
|
||||||
|
EthereumLowerBoundReceiptsDetector(upstream),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ data class LowerBoundData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class LowerBoundType {
|
enum class LowerBoundType {
|
||||||
UNKNOWN, STATE, SLOT, BLOCK, TX, LOGS, TRACE, PROOF, BLOB, EPOCH
|
UNKNOWN, STATE, SLOT, BLOCK, TX, LOGS, TRACE, PROOF, BLOB, EPOCH, RECEIPTS
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BlockchainOuterClass.LowerBoundType.fromProtoType(): LowerBoundType {
|
fun BlockchainOuterClass.LowerBoundType.fromProtoType(): LowerBoundType {
|
||||||
@@ -36,5 +36,6 @@ fun BlockchainOuterClass.LowerBoundType.fromProtoType(): LowerBoundType {
|
|||||||
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_PROOF -> LowerBoundType.PROOF
|
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_PROOF -> LowerBoundType.PROOF
|
||||||
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOB -> LowerBoundType.BLOB
|
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_BLOB -> LowerBoundType.BLOB
|
||||||
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_EPOCH -> LowerBoundType.EPOCH
|
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_EPOCH -> LowerBoundType.EPOCH
|
||||||
|
BlockchainOuterClass.LowerBoundType.LOWER_BOUND_RECEIPTS -> LowerBoundType.RECEIPTS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user