Add height matcher for some methods (#218)

This commit is contained in:
KirillPamPam
2023-05-30 17:28:26 +04:00
committed by GitHub
parent f87c86548e
commit d83e2f1c6b
3 changed files with 119 additions and 97 deletions

View File

@@ -95,10 +95,9 @@ open class NativeCall(
fun onUpstreamChangeEvent(event: UpstreamChangeEvent) { fun onUpstreamChangeEvent(event: UpstreamChangeEvent) {
casting[BlockchainType.from(event.chain)]?.let { cast -> casting[BlockchainType.from(event.chain)]?.let { cast ->
multistreamHolder.getUpstream(event.chain).let { up -> multistreamHolder.getUpstream(event.chain).let { up ->
val reader = up.cast(cast).getReader()
ethereumCallSelectors.putIfAbsent( ethereumCallSelectors.putIfAbsent(
event.chain, event.chain,
EthereumCallSelector(reader.heightByHash(), up.caches) EthereumCallSelector(up.caches)
) )
} }
} }

View File

@@ -18,14 +18,12 @@ package io.emeraldpay.dshackle.upstream.calls
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.etherjar.hex.HexQuantity import io.emeraldpay.etherjar.hex.HexQuantity
import org.bouncycastle.util.encoders.DecoderException import org.bouncycastle.util.encoders.DecoderException
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import java.util.Collections
import java.util.Objects import java.util.Objects
/** /**
@@ -33,7 +31,6 @@ import java.util.Objects
* The implementation is specific for Ethereum. * The implementation is specific for Ethereum.
*/ */
class EthereumCallSelector( class EthereumCallSelector(
private val heightReader: Reader<BlockId, Long>,
private val caches: Caches private val caches: Caches
) { ) {
@@ -41,17 +38,25 @@ class EthereumCallSelector(
private val log = LoggerFactory.getLogger(EthereumCallSelector::class.java) private val log = LoggerFactory.getLogger(EthereumCallSelector::class.java)
// ref https://eth.wiki/json-rpc/API#the-default-block-parameter // ref https://eth.wiki/json-rpc/API#the-default-block-parameter
private val TAG_METHODS = listOf( private val TAG_METHODS = setOf(
"eth_getBalance", "eth_getBalance",
"eth_getCode", "eth_getCode",
"eth_getTransactionCount", "eth_getTransactionCount",
// no "eth_getStorageAt" because it has different structure, and therefore separate logic // no "eth_getStorageAt" because it has different structure, and therefore separate logic
"eth_call" "eth_call",
).sorted() "eth_getRootHash",
"bor_getRootHash"
)
private val FILTER_OBJECT_METHODS = setOf(
"eth_newFilter", "eth_getLogs"
)
private val GET_BY_HASH_OR_NUMBER_METHODS = setOf( private val GET_BY_HASH_OR_NUMBER_METHODS = setOf(
"eth_getBlockByHash", "eth_getBlockByNumber", "eth_getBlockByHash", "eth_getBlockByNumber", "bor_getSignersAtHash",
"eth_getTransactionByBlockHashAndIndex", "eth_getTransactionByBlockNumberAndIndex" "eth_getTransactionByBlockHashAndIndex", "eth_getTransactionByBlockNumberAndIndex",
"eth_getBlockTransactionCountByNumber", "bor_getAuthor", "eth_getUncleCountByBlockNumber",
"eth_getUncleByBlockNumberAndIndex"
) )
} }
@@ -65,14 +70,19 @@ class EthereumCallSelector(
if (method in DefaultEthereumMethods.withFilterIdMethods) { if (method in DefaultEthereumMethods.withFilterIdMethods) {
return sameUpstreamMatcher(params) return sameUpstreamMatcher(params)
} else if (!passthrough) { // passthrough indicates we should match only labels } else if (!passthrough) { // passthrough indicates we should match only labels
if (Collections.binarySearch(TAG_METHODS, method) >= 0) { when (method) {
return blockTagSelector(params, 1, null, head) in TAG_METHODS -> {
} else if (method == "eth_getStorageAt") { return blockTagSelector(params, 1, null, head)
return blockTagSelector(params, 2, null, head) }
} else if (method in GET_BY_HASH_OR_NUMBER_METHODS) { "eth_getStorageAt" -> {
return blockMethodSelector(method, params, head) return blockTagSelector(params, 2, null, head)
} else if (method == "eth_getLogs") { }
return blockTagSelector(params, 0, "toBlock", head) in GET_BY_HASH_OR_NUMBER_METHODS -> {
return blockTagSelector(params, 0, null, head)
}
in FILTER_OBJECT_METHODS -> {
return blockTagSelector(params, 0, "toBlock", head)
}
} }
} }
return Mono.empty() return Mono.empty()
@@ -91,6 +101,7 @@ class EthereumCallSelector(
val nodeId = hashHex.toInt(16) val nodeId = hashHex.toInt(16)
return Mono.just(Selector.SameNodeMatcher(nodeId.toByte())) return Mono.just(Selector.SameNodeMatcher(nodeId.toByte()))
} }
private fun blockTagSelector(params: String, pos: Int, paramName: String?, head: Head): Mono<Selector.Matcher> { private fun blockTagSelector(params: String, pos: Int, paramName: String?, head: Head): Mono<Selector.Matcher> {
val list = objectMapper.readerFor(Any::class.java).readValues<Any>(params).readAll() val list = objectMapper.readerFor(Any::class.java).readValues<Any>(params).readAll()
if (list.size < pos + 1) { if (list.size < pos + 1) {
@@ -131,9 +142,9 @@ class EthereumCallSelector(
val minHeight: Long? = when (tag) { val minHeight: Long? = when (tag) {
"latest" -> head.getCurrentHeight() "latest" -> head.getCurrentHeight()
"earliest" -> 0L // for earliest it doesn't nothing, we expect to have 0 block "earliest" -> 0L // for earliest it doesn't nothing, we expect to have 0 block
else -> if (tag.startsWith("0x")) { else -> if (tag.startsWith("0x") || tag.toLongOrNull() != null) {
return if (tag.length == 66) { // 32-byte hash is represented as 0x + 64 characters return if (tag.length == 66) { // 32-byte hash is represented as 0x + 64 characters
blockByHash(tag, head) blockByHash(tag)
} else { } else {
blockByHeight(tag) blockByHeight(tag)
} }
@@ -148,21 +159,8 @@ class EthereumCallSelector(
Mono.empty() Mono.empty()
} }
} }
private fun blockMethodSelector(method: String, params: String, head: Head): Mono<Selector.Matcher> {
val list = objectMapper.readerFor(Any::class.java).readValues<Any>(params).readAll()
if (list.isEmpty()) {
return Mono.empty()
}
val hashOrNumber = Objects.toString(list[0])
return when (method) { private fun blockByHash(blockHash: String): Mono<Selector.Matcher> {
"eth_getTransactionByBlockHashAndIndex", "eth_getBlockByHash" -> blockByHashFromCache(hashOrNumber)
"eth_getTransactionByBlockNumberAndIndex", "eth_getBlockByNumber" -> blockSelectorByTag(hashOrNumber, head)
else -> Mono.empty()
}
}
private fun blockByHashFromCache(blockHash: String): Mono<Selector.Matcher> {
return try { return try {
caches.getLastHeightByHash() caches.getLastHeightByHash()
.read(BlockId.from(blockHash)) .read(BlockId.from(blockHash))
@@ -176,22 +174,16 @@ class EthereumCallSelector(
private fun blockByHeight(blockNumber: String): Mono<Selector.Matcher> { private fun blockByHeight(blockNumber: String): Mono<Selector.Matcher> {
return try { return try {
Mono.just(Selector.HeightMatcher(HexQuantity.from(blockNumber).value.longValueExact())) val height =
if (blockNumber.startsWith("0x")) {
HexQuantity.from(blockNumber).value.longValueExact()
} else {
blockNumber.toLong()
}
Mono.just(Selector.HeightMatcher(height))
} catch (t: Throwable) { } catch (t: Throwable) {
log.warn("Invalid blockNumber: $blockNumber") log.warn("Invalid blockNumber: $blockNumber")
Mono.empty<Selector.Matcher>() Mono.empty()
}
}
private fun blockByHash(blockHash: String, head: Head): Mono<Selector.Matcher> {
return try {
val blockId = BlockId.from(blockHash)
heightReader.read(blockId)
.switchIfEmpty(Mono.justOrEmpty(head.getCurrentHeight()))
.map { Selector.HeightMatcher(it) }
} catch (t: Throwable) {
log.warn("Invalid blockHash: $blockHash")
Mono.empty<Selector.Matcher>()
} }
} }
} }

View File

@@ -15,11 +15,9 @@
*/ */
package io.emeraldpay.dshackle.upstream.calls package io.emeraldpay.dshackle.upstream.calls
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.HeightByHashMemCache import io.emeraldpay.dshackle.cache.HeightByHashMemCache
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
@@ -32,7 +30,7 @@ class EthereumCallSelectorSpec extends Specification {
def "Get height matcher for latest balance"() { def "Get height matcher for latest balance"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
1 * getCurrentHeight() >> 100 1 * getCurrentHeight() >> 100
} }
@@ -44,7 +42,7 @@ class EthereumCallSelectorSpec extends Specification {
def "Get height matcher for latest call"() { def "Get height matcher for latest call"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
1 * getCurrentHeight() >> 100 1 * getCurrentHeight() >> 100
} }
@@ -56,7 +54,7 @@ class EthereumCallSelectorSpec extends Specification {
def "Get height matcher for latest storageAt"() { def "Get height matcher for latest storageAt"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
1 * getCurrentHeight() >> 100 1 * getCurrentHeight() >> 100
} }
@@ -68,7 +66,7 @@ class EthereumCallSelectorSpec extends Specification {
def "Get height matcher for balance on block"() { def "Get height matcher for balance on block"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 100 _ * getCurrentHeight() >> 100
} }
@@ -80,10 +78,12 @@ class EthereumCallSelectorSpec extends Specification {
def "Get height matcher for balance on block referred by hash"() { def "Get height matcher for balance on block referred by hash"() {
setup: setup:
def heights = Mock(Reader) { def cache = Mock(Caches) { caches ->
1 * it.read(BlockId.from("0xc90f1c8c125a4d5b90742f16947bdb1d10516f173fd7fc51223d10499de2a812")) >> Mono.just(8606722L) 1 * caches.getLastHeightByHash() >> Mock(HeightByHashMemCache) { memCache ->
1 * memCache.read(BlockId.from("0xc90f1c8c125a4d5b90742f16947bdb1d10516f173fd7fc51223d10499de2a812")) >> Mono.just(8606722L)
}
} }
EthereumCallSelector callSelector = new EthereumCallSelector(heights, Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(cache)
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 9128116 _ * getCurrentHeight() >> 9128116
} }
@@ -95,7 +95,7 @@ class EthereumCallSelectorSpec extends Specification {
def "No matcher for invalid height"() { def "No matcher for invalid height"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 100 _ * getCurrentHeight() >> 100
} }
@@ -108,7 +108,7 @@ class EthereumCallSelectorSpec extends Specification {
def "No matcher for negative height"() { def "No matcher for negative height"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 100 _ * getCurrentHeight() >> 100
} }
@@ -120,7 +120,7 @@ class EthereumCallSelectorSpec extends Specification {
def "No matcher for negative long"() { def "No matcher for negative long"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 100 _ * getCurrentHeight() >> 100
} }
@@ -133,7 +133,7 @@ class EthereumCallSelectorSpec extends Specification {
def "No matcher for pending balance"() { def "No matcher for pending balance"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 100 _ * getCurrentHeight() >> 100
} }
@@ -145,7 +145,7 @@ class EthereumCallSelectorSpec extends Specification {
def "Get height matcher with EIP-1898"() { def "Get height matcher with EIP-1898"() {
setup: setup:
EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Reader), Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(Stub(Caches))
def head = Stub(Head) def head = Stub(Head)
when: when:
def act = callSelector.getMatcher("eth_call", '["0x0000", {"blockNumber": "0x100"}]', head, false).block() def act = callSelector.getMatcher("eth_call", '["0x0000", {"blockNumber": "0x100"}]', head, false).block()
@@ -155,10 +155,12 @@ class EthereumCallSelectorSpec extends Specification {
def "Get hash matcher with EIP-1898"() { def "Get hash matcher with EIP-1898"() {
setup: setup:
def heights = Mock(Reader) { def cache = Mock(Caches) { caches ->
1 * it.read(BlockId.from("0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32")) >> Mono.just(12079192L) 1 * caches.getLastHeightByHash() >> Mock(HeightByHashMemCache) { memCache ->
1 * memCache.read(BlockId.from("0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32")) >> Mono.just(12079192L)
}
} }
EthereumCallSelector callSelector = new EthereumCallSelector(heights, Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(cache)
def head = Stub(Head) def head = Stub(Head)
when: when:
def act = callSelector.getMatcher("eth_call", def act = callSelector.getMatcher("eth_call",
@@ -170,10 +172,12 @@ class EthereumCallSelectorSpec extends Specification {
def "Get empty matcher for block tag with passthrough arg"() { def "Get empty matcher for block tag with passthrough arg"() {
setup: setup:
def heights = Mock(Reader) { def cache = Mock(Caches) { caches ->
0 * it.read(BlockId.from("0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32")) >> Mono.just(12079192L) 0 * caches.getLastHeightByHash() >> Mock(HeightByHashMemCache) { memCache ->
0 * memCache.read(BlockId.from("0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32")) >> Mono.just(12079192L)
}
} }
EthereumCallSelector callSelector = new EthereumCallSelector(heights, Stub(Caches)) EthereumCallSelector callSelector = new EthereumCallSelector(cache)
def head = Stub(Head) def head = Stub(Head)
when: when:
def act = callSelector.getMatcher("eth_call", def act = callSelector.getMatcher("eth_call",
@@ -183,26 +187,9 @@ class EthereumCallSelectorSpec extends Specification {
act == null act == null
} }
def "Match head if hash matcher for unknown hash"() {
setup:
def heights = Mock(Reader) {
1 * it.read(BlockId.from("0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32")) >> Mono.empty()
}
EthereumCallSelector callSelector = new EthereumCallSelector(heights, Stub(Caches))
def head = Mock(Head) {
1 * it.getCurrentHeight() >> 100
}
when:
def act = callSelector.getMatcher("eth_call",
'["0x0000", {"blockHash": "0xa6af163aab691919c595e2a466f0a7b01f1dff8cfd9631dee811df57064c2d32"}]', head, false)
.block()
then:
act == new Selector.HeightMatcher(100)
}
def "Get same matcher for getFilterChanges method"() { def "Get same matcher for getFilterChanges method"() {
setup: setup:
def callSelector = new EthereumCallSelector(Mock(Reader), Stub(Caches)) def callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) def head = Mock(Head)
expect: expect:
@@ -219,7 +206,7 @@ class EthereumCallSelectorSpec extends Specification {
def "Get empty matcher for getFilterChanges method without params"() { def "Get empty matcher for getFilterChanges method without params"() {
setup: setup:
def callSelector = new EthereumCallSelector(Mock(Reader), Stub(Caches)) def callSelector = new EthereumCallSelector(Stub(Caches))
def head = Mock(Head) def head = Mock(Head)
when: when:
@@ -238,7 +225,7 @@ class EthereumCallSelectorSpec extends Specification {
1 * memCache.read(BlockId.from(hash)) >> Mono.just(blockHeight) 1 * memCache.read(BlockId.from(hash)) >> Mono.just(blockHeight)
} }
} }
def callSelector = new EthereumCallSelector(Stub(Reader), cache) def callSelector = new EthereumCallSelector(cache)
def head = Stub(Head) def head = Stub(Head)
when: when:
@@ -254,13 +241,13 @@ class EthereumCallSelectorSpec extends Specification {
.verify(Duration.ofSeconds(1)) .verify(Duration.ofSeconds(1))
where: where:
method << ["eth_getTransactionByBlockHashAndIndex", "eth_getBlockByHash"] method << ["eth_getTransactionByBlockHashAndIndex", "eth_getBlockByHash", "bor_getSignersAtHash"]
} }
def "No height matcher for getByNumber and getTransactionByBlockNumber methods when passthrough is on"() { def "No height matcher for getByNumber and getTransactionByBlockNumber methods when passthrough is on"() {
setup: setup:
def cache = Stub(Caches) def cache = Stub(Caches)
def callSelector = new EthereumCallSelector(Stub(Reader), cache) def callSelector = new EthereumCallSelector(cache)
def head = Stub(Head) def head = Stub(Head)
when: when:
@@ -283,10 +270,11 @@ class EthereumCallSelectorSpec extends Specification {
"eth_getBlockByNumber" | '["earliest", false]' "eth_getBlockByNumber" | '["earliest", false]'
"eth_getBlockByNumber" | '["latest", false]' "eth_getBlockByNumber" | '["latest", false]'
} }
def "Get height matcher for getByNumber and getTransactionByBlockNumber methods"() {
def "Get height matcher for byNumber methods"() {
setup: setup:
def cache = Stub(Caches) def cache = Stub(Caches)
def callSelector = new EthereumCallSelector(Stub(Reader), cache) def callSelector = new EthereumCallSelector(cache)
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 17654321L _ * getCurrentHeight() >> 17654321L
} }
@@ -310,6 +298,18 @@ class EthereumCallSelectorSpec extends Specification {
"eth_getBlockByNumber" | '["0xfbfe3b", false]' | 16514619L "eth_getBlockByNumber" | '["0xfbfe3b", false]' | 16514619L
"eth_getBlockByNumber" | '["earliest", false]' | 0L "eth_getBlockByNumber" | '["earliest", false]' | 0L
"eth_getBlockByNumber" | '["latest", false]' | 17654321L "eth_getBlockByNumber" | '["latest", false]' | 17654321L
"eth_getBlockTransactionCountByNumber" | '["latest"]' | 17654321L
"eth_getBlockTransactionCountByNumber" | '["0xfbfe3b"]' | 16514619L
"eth_getBlockTransactionCountByNumber" | '["earliest"]' | 0L
"eth_getUncleCountByBlockNumber" | '["latest"]' | 17654321L
"eth_getUncleCountByBlockNumber" | '["0xfbfe3b"]' | 16514619L
"eth_getUncleCountByBlockNumber" | '["earliest"]' | 0L
"eth_getUncleCountByBlockNumber" | '["latest"]' | 17654321L
"eth_getUncleCountByBlockNumber" | '["0xfbfe3b"]' | 16514619L
"eth_getUncleCountByBlockNumber" | '["earliest"]' | 0L
"eth_getUncleByBlockNumberAndIndex" | '["latest"]' | 17654321L
"eth_getUncleByBlockNumberAndIndex" | '["0xfbfe3b"]' | 16514619L
"eth_getUncleByBlockNumberAndIndex" | '["earliest"]' | 0L
} }
def "No height matcher for getByHash method"() { def "No height matcher for getByHash method"() {
@@ -320,7 +320,7 @@ class EthereumCallSelectorSpec extends Specification {
1 * memCache.read(BlockId.from(hash)) >> resultFromCache 1 * memCache.read(BlockId.from(hash)) >> resultFromCache
} }
} }
def callSelector = new EthereumCallSelector(Stub(Reader), cache) def callSelector = new EthereumCallSelector(cache)
def head = Stub(Head) def head = Stub(Head)
when: when:
@@ -339,10 +339,10 @@ class EthereumCallSelectorSpec extends Specification {
resultFromCache << [Mono.empty(), Mono.error(new RuntimeException())] resultFromCache << [Mono.empty(), Mono.error(new RuntimeException())]
} }
def "Get height matcher for getLogs method"() { def "Get height matcher for getLogs and eth_newFilter method"() {
setup: setup:
def cache = Stub(Caches) def cache = Stub(Caches)
def callSelector = new EthereumCallSelector(Stub(Reader), cache) def callSelector = new EthereumCallSelector(cache)
def head = Mock(Head) { def head = Mock(Head) {
_ * getCurrentHeight() >> 17654321L _ * getCurrentHeight() >> 17654321L
} }
@@ -361,12 +361,15 @@ class EthereumCallSelectorSpec extends Specification {
"eth_getLogs" | '[{"toBlock":"0xfbfe3b"}]' | 16514619L "eth_getLogs" | '[{"toBlock":"0xfbfe3b"}]' | 16514619L
"eth_getLogs" | '[{"toBlock":"latest"}]' | 17654321L "eth_getLogs" | '[{"toBlock":"latest"}]' | 17654321L
"eth_getLogs" | '[{"toBlock":"earliest"}]' | 0L "eth_getLogs" | '[{"toBlock":"earliest"}]' | 0L
"eth_newFilter" | '[{"toBlock":"0xfbfe2b", "toBlock":"0xfbfe3b"}]' | 16514619L
"eth_newFilter" | '[{"toBlock":"0xfbfe3b", "toBlock":"latest"}]' | 17654321L
"eth_newFilter" | '[{"toBlock":"0xfbfe3b", "toBlock":"earliest"}]' | 0L
} }
def "No height matcher for getLogs method when passthrough is on"() { def "No height matcher for getLogs and eth_newFilter method when passthrough is on"() {
setup: setup:
def cache = Stub(Caches) def cache = Stub(Caches)
def callSelector = new EthereumCallSelector(Stub(Reader), cache) def callSelector = new EthereumCallSelector(cache)
def head = Stub(Head) def head = Stub(Head)
when: when:
@@ -383,5 +386,33 @@ class EthereumCallSelectorSpec extends Specification {
"eth_getLogs" | '[{"toBlock":"0xfbfe3b"}]' "eth_getLogs" | '[{"toBlock":"0xfbfe3b"}]'
"eth_getLogs" | '[{"toBlock":"latest"}]' "eth_getLogs" | '[{"toBlock":"latest"}]'
"eth_getLogs" | '[{"toBlock":"earliest"}]' "eth_getLogs" | '[{"toBlock":"earliest"}]'
"eth_newFilter" | '[{"toBlock":"0xfbfe2b", "toBlock":"0xfbfe3b"}]'
"eth_newFilter" | '[{"toBlock":"0xfbfe3b", "toBlock":"latest"}]'
"eth_newFilter" | '[{"toBlock":"0xfbfe3b", "toBlock":"earliest"}]'
}
def "Get height matcher for bor method"() {
setup:
def cache = Stub(Caches)
def callSelector = new EthereumCallSelector(cache)
def head = Mock(Head) {
_ * getCurrentHeight() >> 17654321L
}
when:
def act = callSelector.getMatcher(method, param, head, false)
then:
StepVerifier.create(act)
.expectNext(new Selector.HeightMatcher(height))
.expectComplete()
.verify(Duration.ofSeconds(1))
where:
method | param | height
"eth_getRootHash" | '[1023, 1200]' | 1200L
"bor_getRootHash" | '[1000, 1400]' | 1400L
"bor_getAuthor" | '["latest"]' | 17654321L
"bor_getAuthor" | '["0xfbfe3b"]' | 16514619L
} }
} }