Integrate drpc-logs-oracle (#1096) (#335)

* add oracle jar to build (#1096)
* add oracle config (#1096)
* add eth_getLogsEstimate (#1096)
* add scheduler for oracle (#1096)
* fix tests :[ (#1096)
This commit is contained in:
Nikolay G
2023-11-22 13:45:00 +01:00
committed by GitHub
parent a7f74bb71a
commit 5a154ac817
33 changed files with 369 additions and 73 deletions

View File

@@ -123,8 +123,16 @@ dependencies {
implementation(variantOf(libs.netty.tcnative.boringssl) { classifier("linux-x86_64") }) implementation(variantOf(libs.netty.tcnative.boringssl) { classifier("linux-x86_64") })
implementation(variantOf(libs.netty.tcnative.boringssl) { classifier("osx-x86_64") }) implementation(variantOf(libs.netty.tcnative.boringssl) { classifier("osx-x86_64") })
implementation 'dshackle:foundation:1.0.0' implementation 'dshackle:foundation:1.0.0'
implementation files('src/main/resources/LogsOracle.jar')
} }
// Enable 'Foreign Function & Memory API' (JEP 434)
// Drop after update on Java 21
tasks.withType(JavaCompile) { options.compilerArgs += "--enable-preview" }
tasks.withType(Test) { jvmArgs += "--enable-preview" }
tasks.withType(JavaExec) { jvmArgs += "--enable-preview" }
compileKotlin { compileKotlin {
compilerOptions.jvmTarget.set(JvmTarget.JVM_20) compilerOptions.jvmTarget.set(JvmTarget.JVM_20)
} }
@@ -327,4 +335,4 @@ ktlint {
} }
} }
compileKotlin.dependsOn chainscodegen compileKotlin.dependsOn chainscodegen

View File

@@ -21,6 +21,7 @@ import io.emeraldpay.dshackle.config.CacheConfig
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.CompressionConfig import io.emeraldpay.dshackle.config.CompressionConfig
import io.emeraldpay.dshackle.config.HealthConfig import io.emeraldpay.dshackle.config.HealthConfig
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.config.MainConfig import io.emeraldpay.dshackle.config.MainConfig
import io.emeraldpay.dshackle.config.MainConfigReader import io.emeraldpay.dshackle.config.MainConfigReader
import io.emeraldpay.dshackle.config.MonitoringConfig import io.emeraldpay.dshackle.config.MonitoringConfig
@@ -130,6 +131,11 @@ open class Config(
return mainConfig.cache ?: CacheConfig() return mainConfig.cache ?: CacheConfig()
} }
@Bean
open fun indexConfig(@Autowired mainConfig: MainConfig): IndexConfig {
return mainConfig.index ?: IndexConfig()
}
@Bean @Bean
open fun signatureConfig(@Autowired mainConfig: MainConfig): SignatureConfig { open fun signatureConfig(@Autowired mainConfig: MainConfig): SignatureConfig {
return mainConfig.signature ?: SignatureConfig() return mainConfig.signature ?: SignatureConfig()

View File

@@ -0,0 +1,21 @@
package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.Chain
class IndexConfig {
var items: HashMap<Chain, Index> = HashMap<Chain, Index>()
class Index(
var rpc: String,
var store: String,
var ram_limit: Long?,
)
fun isChainEnabled(chain: Chain): Boolean {
return items.containsKey(chain)
}
fun getByChain(chain: Chain): Index? {
return items.get(chain)
}
}

View File

@@ -0,0 +1,62 @@
package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.foundation.YamlConfigReader
import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory
import org.springframework.util.unit.DataSize
import org.yaml.snakeyaml.nodes.MappingNode
class IndexConfigReader : YamlConfigReader<IndexConfig>() {
companion object {
private val log = LoggerFactory.getLogger(IndexConfigReader::class.java)
}
override fun read(input: MappingNode?): IndexConfig? {
return getList<MappingNode>(input, "index")?.let { items ->
val config = IndexConfig()
items.value.map {
val blockchainRaw = getValueAsString(it, "chain")
if (blockchainRaw == null || StringUtils.isEmpty(blockchainRaw) || Global.chainById(blockchainRaw) == Chain.UNSPECIFIED) {
throw InvalidConfigYamlException(filename, it.startMark, "Invalid blockchain or not specified")
}
val blockchain = Global.chainById(blockchainRaw)
if (config.items.containsKey(blockchain)) {
throw InvalidConfigYamlException(filename, it.startMark, "Duplicated indexes")
}
val rpc = getValueAsString(it, "rpc")
if (rpc == null || StringUtils.isEmpty(rpc)) {
throw InvalidConfigYamlException(filename, it.startMark, "Invalid rpc specified")
}
val store = getValueAsString(it, "store")
if (store == null || StringUtils.isEmpty(store)) {
throw InvalidConfigYamlException(filename, it.startMark, "Invalid store directory or not specified")
}
val limit = getMapping(it, "limit")
val ram_limit = limit?.let {
val raw = getValueAsString(limit, "ram")
if (raw == null || StringUtils.isEmpty(raw)) {
return null
}
try {
DataSize.parse(raw).toBytes()
} catch (e: IllegalArgumentException) {
throw InvalidConfigYamlException(filename, it.startMark, "Invalid limit for index")
}
}
config.items.put(blockchain, IndexConfig.Index(rpc, store, ram_limit))
}
config
}
}
}

View File

@@ -21,6 +21,7 @@ class MainConfig {
var tls: AuthConfig.ServerTlsAuth? = null var tls: AuthConfig.ServerTlsAuth? = null
var passthrough: Boolean = false var passthrough: Boolean = false
var cache: CacheConfig? = null var cache: CacheConfig? = null
var index: IndexConfig? = null
var proxy: ProxyConfig? = null var proxy: ProxyConfig? = null
var upstreams: UpstreamsConfig? = null var upstreams: UpstreamsConfig? = null
var tokens: TokensConfig? = null var tokens: TokensConfig? = null

View File

@@ -29,6 +29,7 @@ class MainConfigReader(
private val optionsReader = ChainOptionsReader() private val optionsReader = ChainOptionsReader()
private val upstreamsConfigReader = UpstreamsConfigReader(fileResolver, optionsReader) private val upstreamsConfigReader = UpstreamsConfigReader(fileResolver, optionsReader)
private val cacheConfigReader = CacheConfigReader() private val cacheConfigReader = CacheConfigReader()
private val indexConfigReader = IndexConfigReader()
private val tokensConfigReader = TokensConfigReader() private val tokensConfigReader = TokensConfigReader()
private val monitoringConfigReader = MonitoringConfigReader() private val monitoringConfigReader = MonitoringConfigReader()
private val accessLogReader = AccessLogReader() private val accessLogReader = AccessLogReader()
@@ -63,6 +64,9 @@ class MainConfigReader(
cacheConfigReader.read(input)?.let { cacheConfigReader.read(input)?.let {
config.cache = it config.cache = it
} }
indexConfigReader.read(input)?.let {
config.index = it
}
tokensConfigReader.read(input)?.let { tokensConfigReader.read(input)?.let {
config.tokens = it config.tokens = it
} }

View File

@@ -3,6 +3,7 @@ package io.emeraldpay.dshackle.config.context
import io.emeraldpay.dshackle.BlockchainType.BITCOIN import io.emeraldpay.dshackle.BlockchainType.BITCOIN
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.CachesFactory import io.emeraldpay.dshackle.cache.CachesFactory
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.upstream.CallTargetsHolder import io.emeraldpay.dshackle.upstream.CallTargetsHolder
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
@@ -26,6 +27,9 @@ open class MultistreamsConfig(val beanFactory: ConfigurableListableBeanFactory)
headScheduler: Scheduler, headScheduler: Scheduler,
tracer: Tracer, tracer: Tracer,
multistreamEventsScheduler: Scheduler, multistreamEventsScheduler: Scheduler,
indexConfig: IndexConfig,
@Qualifier("logsOracleScheduler")
logsOracleScheduler: Scheduler,
): List<Multistream> { ): List<Multistream> {
return Chain.entries return Chain.entries
.filterNot { it == Chain.UNSPECIFIED } .filterNot { it == Chain.UNSPECIFIED }
@@ -33,7 +37,15 @@ open class MultistreamsConfig(val beanFactory: ConfigurableListableBeanFactory)
if (chain.type == BITCOIN) { if (chain.type == BITCOIN) {
bitcoinMultistream(chain, cachesFactory, headScheduler, multistreamEventsScheduler) bitcoinMultistream(chain, cachesFactory, headScheduler, multistreamEventsScheduler)
} else { } else {
genericMultistream(chain, cachesFactory, headScheduler, tracer, multistreamEventsScheduler) genericMultistream(
chain,
cachesFactory,
headScheduler,
tracer,
multistreamEventsScheduler,
indexConfig.getByChain(chain),
logsOracleScheduler,
)
} }
} }
} }
@@ -44,6 +56,8 @@ open class MultistreamsConfig(val beanFactory: ConfigurableListableBeanFactory)
headScheduler: Scheduler, headScheduler: Scheduler,
tracer: Tracer, tracer: Tracer,
multistreamEventsScheduler: Scheduler, multistreamEventsScheduler: Scheduler,
logsOracleConfig: IndexConfig.Index?,
logsOracleScheduler: Scheduler,
): Multistream { ): Multistream {
val name = "multi-$chain" val name = "multi-$chain"
val cs = ChainSpecificRegistry.resolve(chain) val cs = ChainSpecificRegistry.resolve(chain)
@@ -58,6 +72,8 @@ open class MultistreamsConfig(val beanFactory: ConfigurableListableBeanFactory)
cs.makeCachingReaderBuilder(tracer), cs.makeCachingReaderBuilder(tracer),
cs::localReaderBuilder, cs::localReaderBuilder,
cs.subscriptionBuilder(headScheduler), cs.subscriptionBuilder(headScheduler),
logsOracleConfig,
logsOracleScheduler,
).also { register(it, name) } ).also { register(it, name) }
} }

View File

@@ -30,6 +30,11 @@ open class SchedulersConfig {
return makeScheduler("head-scheduler", 4, monitoringConfig) return makeScheduler("head-scheduler", 4, monitoringConfig)
} }
@Bean
open fun logsOracleScheduler(monitoringConfig: MonitoringConfig): Scheduler {
return makeScheduler("logs-oracle", 4, monitoringConfig)
}
@Bean @Bean
open fun multistreamEventsScheduler(monitoringConfig: MonitoringConfig): Scheduler { open fun multistreamEventsScheduler(monitoringConfig: MonitoringConfig): Scheduler {
return makeScheduler("events-scheduler", 4, monitoringConfig) return makeScheduler("events-scheduler", 4, monitoringConfig)

View File

@@ -3,6 +3,7 @@ package io.emeraldpay.dshackle.startup.configure
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.FileResolver import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.foundation.ChainOptions import io.emeraldpay.dshackle.foundation.ChainOptions
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
@@ -24,11 +25,12 @@ import java.util.concurrent.atomic.AtomicInteger
@Component @Component
class BitcoinUpstreamCreator( class BitcoinUpstreamCreator(
chainsConfig: ChainsConfig, chainsConfig: ChainsConfig,
indexConfig: IndexConfig,
callTargets: CallTargetsHolder, callTargets: CallTargetsHolder,
private val genericConnectorFactoryCreator: ConnectorFactoryCreator, private val genericConnectorFactoryCreator: ConnectorFactoryCreator,
private val fileResolver: FileResolver, private val fileResolver: FileResolver,
private val headScheduler: Scheduler, private val headScheduler: Scheduler,
) : UpstreamCreator(chainsConfig, callTargets) { ) : UpstreamCreator(chainsConfig, indexConfig, callTargets) {
private var seq = AtomicInteger(0) private var seq = AtomicInteger(0)
override fun createUpstream( override fun createUpstream(

View File

@@ -2,6 +2,7 @@ package io.emeraldpay.dshackle.startup.configure
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.foundation.ChainOptions import io.emeraldpay.dshackle.foundation.ChainOptions
import io.emeraldpay.dshackle.upstream.CallTargetsHolder import io.emeraldpay.dshackle.upstream.CallTargetsHolder
@@ -11,9 +12,10 @@ import org.springframework.stereotype.Component
@Component @Component
class EthereumUpstreamCreator( class EthereumUpstreamCreator(
chainsConfig: ChainsConfig, chainsConfig: ChainsConfig,
indexConfig: IndexConfig,
callTargets: CallTargetsHolder, callTargets: CallTargetsHolder,
genericConnectorFactoryCreator: ConnectorFactoryCreator, genericConnectorFactoryCreator: ConnectorFactoryCreator,
) : GenericUpstreamCreator(chainsConfig, callTargets, genericConnectorFactoryCreator) { ) : GenericUpstreamCreator(chainsConfig, indexConfig, callTargets, genericConnectorFactoryCreator) {
override fun createUpstream( override fun createUpstream(
upstreamsConfig: UpstreamsConfig.Upstream<*>, upstreamsConfig: UpstreamsConfig.Upstream<*>,

View File

@@ -2,6 +2,7 @@ package io.emeraldpay.dshackle.startup.configure
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.foundation.ChainOptions import io.emeraldpay.dshackle.foundation.ChainOptions
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
@@ -19,9 +20,10 @@ import kotlin.math.abs
@Component @Component
open class GenericUpstreamCreator( open class GenericUpstreamCreator(
chainsConfig: ChainsConfig, chainsConfig: ChainsConfig,
indexConfig: IndexConfig,
callTargets: CallTargetsHolder, callTargets: CallTargetsHolder,
private val genericConnectorFactoryCreator: ConnectorFactoryCreator, private val genericConnectorFactoryCreator: ConnectorFactoryCreator,
) : UpstreamCreator(chainsConfig, callTargets) { ) : UpstreamCreator(chainsConfig, indexConfig, callTargets) {
private val hashes: MutableMap<Byte, Boolean> = HashMap() private val hashes: MutableMap<Byte, Boolean> = HashMap()
override fun createUpstream( override fun createUpstream(

View File

@@ -3,6 +3,7 @@ package io.emeraldpay.dshackle.startup.configure
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.config.ChainsConfig import io.emeraldpay.dshackle.config.ChainsConfig
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.foundation.ChainOptions import io.emeraldpay.dshackle.foundation.ChainOptions
import io.emeraldpay.dshackle.upstream.CallTargetsHolder import io.emeraldpay.dshackle.upstream.CallTargetsHolder
@@ -14,6 +15,7 @@ import org.slf4j.LoggerFactory
abstract class UpstreamCreator( abstract class UpstreamCreator(
private val chainsConfig: ChainsConfig, private val chainsConfig: ChainsConfig,
private val indexConfig: IndexConfig,
private val callTargets: CallTargetsHolder, private val callTargets: CallTargetsHolder,
) { ) {
protected val log: Logger = LoggerFactory.getLogger(this::class.java) protected val log: Logger = LoggerFactory.getLogger(this::class.java)
@@ -45,7 +47,7 @@ abstract class UpstreamCreator(
protected fun buildMethods(config: UpstreamsConfig.Upstream<*>, chain: Chain): CallMethods { protected fun buildMethods(config: UpstreamsConfig.Upstream<*>, chain: Chain): CallMethods {
return if (config.methods != null || config.methodGroups != null) { return if (config.methods != null || config.methodGroups != null) {
ManagedCallMethods( ManagedCallMethods(
delegate = callTargets.getDefaultMethods(chain), delegate = callTargets.getDefaultMethods(chain, indexConfig.isChainEnabled(chain)),
enabled = config.methods?.enabled?.map { it.name }?.toSet() ?: emptySet(), enabled = config.methods?.enabled?.map { it.name }?.toSet() ?: emptySet(),
disabled = config.methods?.disabled?.map { it.name }?.toSet() ?: emptySet(), disabled = config.methods?.disabled?.map { it.name }?.toSet() ?: emptySet(),
groupsEnabled = config.methodGroups?.enabled ?: emptySet(), groupsEnabled = config.methodGroups?.enabled ?: emptySet(),
@@ -61,7 +63,7 @@ abstract class UpstreamCreator(
} }
} }
} else { } else {
callTargets.getDefaultMethods(chain) callTargets.getDefaultMethods(chain, indexConfig.isChainEnabled(chain))
} }
} }
} }

View File

@@ -18,14 +18,14 @@ import org.springframework.stereotype.Component
class CallTargetsHolder { class CallTargetsHolder {
private val callTargets = HashMap<Chain, CallMethods>() private val callTargets = HashMap<Chain, CallMethods>()
fun getDefaultMethods(chain: Chain): CallMethods { fun getDefaultMethods(chain: Chain, hasLogsOracle: Boolean): CallMethods {
return callTargets[chain] ?: return setupDefaultMethods(chain) return callTargets[chain] ?: return setupDefaultMethods(chain, hasLogsOracle)
} }
private fun setupDefaultMethods(chain: Chain): CallMethods { private fun setupDefaultMethods(chain: Chain, hasLogsOracle: Boolean): CallMethods {
val created = when (chain.type) { val created = when (chain.type) {
BITCOIN -> DefaultBitcoinMethods() BITCOIN -> DefaultBitcoinMethods()
ETHEREUM -> DefaultEthereumMethods(chain) ETHEREUM -> DefaultEthereumMethods(chain, hasLogsOracle)
STARKNET -> DefaultStarknetMethods(chain) STARKNET -> DefaultStarknetMethods(chain)
POLKADOT -> DefaultPolkadotMethods() POLKADOT -> DefaultPolkadotMethods()
SOLANA -> DefaultSolanaMethods() SOLANA -> DefaultSolanaMethods()

View File

@@ -0,0 +1,42 @@
package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.config.IndexConfig
import org.slf4j.LoggerFactory
import reactor.core.Disposable
import reactor.core.publisher.Mono
import reactor.core.scheduler.Scheduler
class LogsOracle(
private val config: IndexConfig.Index,
private val upstream: Multistream,
private val scheduler: Scheduler,
) {
private val log = LoggerFactory.getLogger(LogsOracle::class.java)
private var subscription: Disposable? = null
private val db = org.drpc.logsoracle.LogsOracle(config.store, config.store, config.ram_limit ?: 0L)
fun start() {
subscription = upstream.getHead().getFlux()
.doOnError { t -> log.warn("Failed to subscribe head for oracle", t) }
.subscribe { println(it.height); db.UpdateHeight(it.height) }
}
fun stop() {
db.close()
subscription?.dispose()
subscription = null
}
fun estimate(
fromBlock: Long?,
toBlock: Long?,
address: List<String>,
topics: List<List<String>>,
): Mono<Long> {
return Mono.fromCallable { db.Query(fromBlock, toBlock, address, topics) }
.subscribeOn(scheduler)
}
}

View File

@@ -32,6 +32,7 @@ import io.emeraldpay.etherjar.rpc.RpcException
*/ */
class DefaultEthereumMethods( class DefaultEthereumMethods(
private val chain: Chain, private val chain: Chain,
private val hasLogsOracle: Boolean = false,
) : CallMethods { ) : CallMethods {
private val version = "\"EmeraldDshackle/${Global.version}\"" private val version = "\"EmeraldDshackle/${Global.version}\""
@@ -137,6 +138,7 @@ class DefaultEthereumMethods(
specialMethods + specialMethods +
headVerifiedMethods - headVerifiedMethods -
chainUnsupportedMethods(chain) + chainUnsupportedMethods(chain) +
getDrpcVendorMethods(chain) +
getChainSpecificMethods(chain) getChainSpecificMethods(chain)
} }
@@ -148,6 +150,7 @@ class DefaultEthereumMethods(
firstValueMethods.contains(method) -> AlwaysQuorum() firstValueMethods.contains(method) -> AlwaysQuorum()
anyResponseMethods.contains(method) -> NotLaggingQuorum(4) anyResponseMethods.contains(method) -> NotLaggingQuorum(4)
headVerifiedMethods.contains(method) -> NotLaggingQuorum(1) headVerifiedMethods.contains(method) -> NotLaggingQuorum(1)
getDrpcVendorMethods(chain).contains(method) -> AlwaysQuorum()
possibleNotIndexedMethods.contains(method) -> NotNullQuorum() possibleNotIndexedMethods.contains(method) -> NotNullQuorum()
specialMethods.contains(method) -> { specialMethods.contains(method) -> {
when (method) { when (method) {
@@ -174,6 +177,15 @@ class DefaultEthereumMethods(
} }
} }
private fun getDrpcVendorMethods(chain: Chain): List<String> {
val supported = mutableListOf<String>()
// Currently tested on eth mainnet only, should potentially work for all compatible ones.
if (chain == Chain.ETHEREUM__MAINNET && hasLogsOracle) { supported.add("drpc_getLogsEstimate") }
return supported
}
private fun getChainSpecificMethods(chain: Chain): List<String> { private fun getChainSpecificMethods(chain: Chain): List<String> {
return when (chain) { return when (chain) {
Chain.OPTIMISM__MAINNET, Chain.OPTIMISM__GOERLI -> listOf( Chain.OPTIMISM__MAINNET, Chain.OPTIMISM__GOERLI -> listOf(

View File

@@ -11,6 +11,7 @@ import io.emeraldpay.dshackle.upstream.EgressSubscription
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.IngressSubscription import io.emeraldpay.dshackle.upstream.IngressSubscription
import io.emeraldpay.dshackle.upstream.LabelsDetector import io.emeraldpay.dshackle.upstream.LabelsDetector
import io.emeraldpay.dshackle.upstream.LogsOracle
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamValidator import io.emeraldpay.dshackle.upstream.UpstreamValidator
@@ -48,8 +49,9 @@ object EthereumChainSpecific : AbstractPollChainSpecific() {
cachingReader: CachingReader, cachingReader: CachingReader,
methods: CallMethods, methods: CallMethods,
head: Head, head: Head,
logsOracle: LogsOracle?,
): Mono<JsonRpcReader> { ): Mono<JsonRpcReader> {
return Mono.just(EthereumLocalReader(cachingReader as EthereumCachingReader, methods, head)) return Mono.just(EthereumLocalReader(cachingReader as EthereumCachingReader, methods, head, logsOracle))
} }
override fun subscriptionBuilder(headScheduler: Scheduler): (Multistream) -> EgressSubscription { override fun subscriptionBuilder(headScheduler: Scheduler): (Multistream) -> EgressSubscription {

View File

@@ -20,6 +20,7 @@ import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxId import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.reader.JsonRpcReader
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.LogsOracle
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
@@ -41,6 +42,7 @@ class EthereumLocalReader(
private val reader: EthereumCachingReader, private val reader: EthereumCachingReader,
private val methods: CallMethods, private val methods: CallMethods,
private val head: Head, private val head: Head,
private val logsOracle: LogsOracle?,
) : JsonRpcReader { ) : JsonRpcReader {
override fun read(key: JsonRpcRequest): Mono<JsonRpcResponse> { override fun read(key: JsonRpcRequest): Mono<JsonRpcResponse> {
@@ -120,6 +122,9 @@ class EthereumLocalReader(
.read(hash) .read(hash)
.map { it.data to it.upstreamId } .map { it.data to it.upstreamId }
} }
method == "drpc_getLogsEstimate" -> {
getLogsEstimate(params)
}
else -> null else -> null
} }
} }
@@ -167,4 +172,82 @@ class EthereumLocalReader(
return reader.blocksByHeightAsCont() return reader.blocksByHeightAsCont()
.read(number).map { it.data.json!! to it.upstreamId } .read(number).map { it.data.json!! to it.upstreamId }
} }
fun getLogsEstimate(params: List<Any?>): Mono<Pair<ByteArray, String?>>? {
if (logsOracle == null) {
throw NotImplementedError()
}
if (params.size != 1 || params[0] == null) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Must provide 1 parameters")
}
val req = params[0] as LinkedHashMap<String, Any?>
val fromBlock = try { parseBlockRef(req.get("fromBlock") as String?) } catch (_: IllegalArgumentException) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Invalid 'fromBlock' parameter")
}
val toBlock = try { parseBlockRef(req.get("toBlock") as String?) } catch (_: IllegalArgumentException) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Invalid 'toBlock' parameter")
}
val address: List<String> = try {
val it = req.get("address") ?: listOf<String>()
if (it is String) {
listOf<String>(it)
} else {
it as List<String>
}
} catch (_: Exception) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Invalid 'address' parameter")
}
val topics: List<List<String>> = try {
val tpcs = req.get("topics")?.let { it as List<Any> } ?: listOf<Any>()
if (tpcs.size > 4) {
throw IllegalArgumentException()
}
tpcs.map {
if (it is String) {
listOf<String>(it)
} else {
it as List<String>
}
}
} catch (_: Exception) {
throw RpcException(RpcResponseError.CODE_INVALID_METHOD_PARAMS, "Invalid 'topics' parameter")
}
return logsOracle.estimate(fromBlock, toBlock, address, topics)
.map { it.toString().toByteArray() to null }
}
private fun parseBlockRef(blockRef: String?): Long? {
when {
blockRef == null -> {
return null
}
blockRef == "latest" -> {
return head.getCurrentHeight() ?: return null
}
blockRef == "earliest" -> {
return 0
}
blockRef == "finalized" || blockRef == "safe" || blockRef == "pending" -> {
return null
}
blockRef.startsWith("0x") -> {
val quantity = HexQuantity.from(blockRef) ?: throw IllegalArgumentException()
return quantity.value.let {
if (it < BigInteger.valueOf(Long.MAX_VALUE) && it >= BigInteger.ZERO) {
it.toLong()
} else {
throw IllegalArgumentException()
}
}
}
else -> {
throw IllegalArgumentException()
}
}
}
} }

View File

@@ -12,6 +12,7 @@ import io.emeraldpay.dshackle.upstream.EmptyEgressSubscription
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.IngressSubscription import io.emeraldpay.dshackle.upstream.IngressSubscription
import io.emeraldpay.dshackle.upstream.LabelsDetector import io.emeraldpay.dshackle.upstream.LabelsDetector
import io.emeraldpay.dshackle.upstream.LogsOracle
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.NoIngressSubscription import io.emeraldpay.dshackle.upstream.NoIngressSubscription
import io.emeraldpay.dshackle.upstream.NoopCachingReader import io.emeraldpay.dshackle.upstream.NoopCachingReader
@@ -31,6 +32,7 @@ abstract class AbstractChainSpecific : ChainSpecific {
cachingReader: CachingReader, cachingReader: CachingReader,
methods: CallMethods, methods: CallMethods,
head: Head, head: Head,
logsOracle: LogsOracle?,
): Mono<JsonRpcReader> { ): Mono<JsonRpcReader> {
return Mono.just(LocalReader(methods)) return Mono.just(LocalReader(methods))
} }

View File

@@ -17,6 +17,7 @@ import io.emeraldpay.dshackle.upstream.EgressSubscription
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.IngressSubscription import io.emeraldpay.dshackle.upstream.IngressSubscription
import io.emeraldpay.dshackle.upstream.LabelsDetector import io.emeraldpay.dshackle.upstream.LabelsDetector
import io.emeraldpay.dshackle.upstream.LogsOracle
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamValidator import io.emeraldpay.dshackle.upstream.UpstreamValidator
@@ -34,7 +35,7 @@ import reactor.core.publisher.Mono
import reactor.core.scheduler.Scheduler import reactor.core.scheduler.Scheduler
typealias SubscriptionBuilder = (Multistream) -> EgressSubscription typealias SubscriptionBuilder = (Multistream) -> EgressSubscription
typealias LocalReaderBuilder = (CachingReader, CallMethods, Head) -> Mono<JsonRpcReader> typealias LocalReaderBuilder = (CachingReader, CallMethods, Head, LogsOracle?) -> Mono<JsonRpcReader>
typealias CachingReaderBuilder = (Multistream, Caches, Factory<CallMethods>) -> CachingReader typealias CachingReaderBuilder = (Multistream, Caches, Factory<CallMethods>) -> CachingReader
interface ChainSpecific { interface ChainSpecific {
@@ -46,7 +47,7 @@ interface ChainSpecific {
fun unsubscribeNewHeadsRequest(subId: String): JsonRpcRequest fun unsubscribeNewHeadsRequest(subId: String): JsonRpcRequest
fun localReaderBuilder(cachingReader: CachingReader, methods: CallMethods, head: Head): Mono<JsonRpcReader> fun localReaderBuilder(cachingReader: CachingReader, methods: CallMethods, head: Head, logsOracle: LogsOracle?): Mono<JsonRpcReader>
fun subscriptionBuilder(headScheduler: Scheduler): (Multistream) -> EgressSubscription fun subscriptionBuilder(headScheduler: Scheduler): (Multistream) -> EgressSubscription

View File

@@ -19,6 +19,7 @@ package io.emeraldpay.dshackle.upstream.generic
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.Chain import io.emeraldpay.dshackle.Chain
import io.emeraldpay.dshackle.cache.Caches import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.config.IndexConfig
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.reader.JsonRpcReader import io.emeraldpay.dshackle.reader.JsonRpcReader
@@ -31,6 +32,7 @@ import io.emeraldpay.dshackle.upstream.EmptyHead
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.HeadLagObserver import io.emeraldpay.dshackle.upstream.HeadLagObserver
import io.emeraldpay.dshackle.upstream.Lifecycle import io.emeraldpay.dshackle.upstream.Lifecycle
import io.emeraldpay.dshackle.upstream.LogsOracle
import io.emeraldpay.dshackle.upstream.MergedHead import io.emeraldpay.dshackle.upstream.MergedHead
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.Selector import io.emeraldpay.dshackle.upstream.Selector
@@ -58,6 +60,8 @@ open class GenericMultistream(
cachingReaderBuilder: CachingReaderBuilder, cachingReaderBuilder: CachingReaderBuilder,
private val localReaderBuilder: LocalReaderBuilder, private val localReaderBuilder: LocalReaderBuilder,
private val subscriptionBuilder: SubscriptionBuilder, private val subscriptionBuilder: SubscriptionBuilder,
logsOracleConfig: IndexConfig.Index? = null,
private val logsOracleScheduler: Scheduler,
) : Multistream(chain, caches, callSelector, multistreamEventsScheduler) { ) : Multistream(chain, caches, callSelector, multistreamEventsScheduler) {
private val cachingReader = cachingReaderBuilder(this, caches, getMethodsFactory()) private val cachingReader = cachingReaderBuilder(this, caches, getMethodsFactory())
@@ -76,6 +80,10 @@ open class GenericMultistream(
headScheduler, headScheduler,
) )
private val logsOracle: LogsOracle? = logsOracleConfig?.let {
LogsOracle(logsOracleConfig, this, logsOracleScheduler)
}
private var subscription: EgressSubscription = subscriptionBuilder(this) private var subscription: EgressSubscription = subscriptionBuilder(this)
private val filteredHeads: MutableMap<String, Head> = private val filteredHeads: MutableMap<String, Head> =
@@ -86,12 +94,14 @@ open class GenericMultistream(
head.start() head.start()
onHeadUpdated(head) onHeadUpdated(head)
cachingReader.start() cachingReader.start()
logsOracle?.start()
} }
override fun stop() { override fun stop() {
super.stop() super.stop()
cachingReader.stop() cachingReader.stop()
filteredHeads.clear() filteredHeads.clear()
logsOracle?.stop()
} }
override fun addHead(upstream: Upstream) { override fun addHead(upstream: Upstream) {
@@ -181,7 +191,7 @@ open class GenericMultistream(
} }
override fun getLocalReader(): Mono<JsonRpcReader> { override fun getLocalReader(): Mono<JsonRpcReader> {
return localReaderBuilder(cachingReader, getMethods(), getHead()) return localReaderBuilder(cachingReader, getMethods(), getHead(), logsOracle)
} }
override fun getEgressSubscription(): EgressSubscription { override fun getEgressSubscription(): EgressSubscription {

View File

@@ -14,6 +14,7 @@ import io.emeraldpay.dshackle.upstream.EgressSubscription
import io.emeraldpay.dshackle.upstream.Head import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.IngressSubscription import io.emeraldpay.dshackle.upstream.IngressSubscription
import io.emeraldpay.dshackle.upstream.LabelsDetector import io.emeraldpay.dshackle.upstream.LabelsDetector
import io.emeraldpay.dshackle.upstream.LogsOracle
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.NoopCachingReader import io.emeraldpay.dshackle.upstream.NoopCachingReader
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
@@ -74,6 +75,7 @@ object PolkadotChainSpecific : AbstractPollChainSpecific() {
cachingReader: CachingReader, cachingReader: CachingReader,
methods: CallMethods, methods: CallMethods,
head: Head, head: Head,
logsOracle: LogsOracle?,
): Mono<JsonRpcReader> { ): Mono<JsonRpcReader> {
return Mono.just(LocalReader(methods)) return Mono.just(LocalReader(methods))
} }

Binary file not shown.

View File

@@ -398,7 +398,7 @@ class NativeCallSpec extends Specification {
def "Prepare call adds height selector for not-lagging quorum"() { def "Prepare call adds height selector for not-lagging quorum"() {
setup: setup:
def methods = new ManagedCallMethods( def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["foo_bar"] as Set, [] as Set, [] as Set, [] as Set ["foo_bar"] as Set, [] as Set, [] as Set, [] as Set
) )
methods.setQuorum("foo_bar", "not_lagging") methods.setQuorum("foo_bar", "not_lagging")
@@ -439,7 +439,7 @@ class NativeCallSpec extends Specification {
def "Prepare call adds decorator for eth_newFilter"() { def "Prepare call adds decorator for eth_newFilter"() {
setup: setup:
def methods = new ManagedCallMethods( def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["eth_newFilter"] as Set, [] as Set, [] as Set, [] as Set ["eth_newFilter"] as Set, [] as Set, [] as Set, [] as Set
) )
methods.setQuorum("eth_newFilter", "always") methods.setQuorum("eth_newFilter", "always")
@@ -470,7 +470,7 @@ class NativeCallSpec extends Specification {
def "Prepare call adds decorator for eth_getFilterChanges"() { def "Prepare call adds decorator for eth_getFilterChanges"() {
setup: setup:
def methods = new ManagedCallMethods( def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["eth_getFilterChanges"] as Set, [] as Set, [] as Set, [] as Set ["eth_getFilterChanges"] as Set, [] as Set, [] as Set, [] as Set
) )
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, TestingCommons.upstream()) def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, TestingCommons.upstream())
@@ -500,7 +500,7 @@ class NativeCallSpec extends Specification {
def "Prepare call adds decorator for eth_uninstallFilter"() { def "Prepare call adds decorator for eth_uninstallFilter"() {
setup: setup:
def methods = new ManagedCallMethods( def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["eth_uninstallFilter"] as Set, [] as Set, [] as Set, [] as Set ["eth_uninstallFilter"] as Set, [] as Set, [] as Set, [] as Set
) )
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, TestingCommons.upstream()) def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, TestingCommons.upstream())
@@ -600,7 +600,7 @@ class NativeCallSpec extends Specification {
} }
def quorum = new AlwaysQuorum() def quorum = new AlwaysQuorum()
def methods = new ManagedCallMethods( def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
[] as Set, [] as Set, ["filter"] as Set, [] as Set [] as Set, [] as Set, ["filter"] as Set, [] as Set
) )
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, new ArrayList<GenericUpstream>()) def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, new ArrayList<GenericUpstream>())
@@ -636,7 +636,7 @@ class NativeCallSpec extends Specification {
} }
def quorum = new AlwaysQuorum() def quorum = new AlwaysQuorum()
def methods = new ManagedCallMethods( def methods = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
[] as Set, [] as Set, ["filter"] as Set, [] as Set [] as Set, [] as Set, ["filter"] as Set, [] as Set
) )
def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, new ArrayList<GenericUpstream>()) def multistream = new MultistreamHolderMock.EthereumMultistreamMock(Chain.ETHEREUM__MAINNET, new ArrayList<GenericUpstream>())

View File

@@ -36,7 +36,7 @@ class GenericUpstreamMock extends GenericUpstream {
static CallMethods allMethods() { static CallMethods allMethods() {
new AggregatedCallMethods([ new AggregatedCallMethods([
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
new DefaultBitcoinMethods(), new DefaultBitcoinMethods(),
new DirectCallMethods(["eth_test"]) new DirectCallMethods(["eth_test"])
]) ])

View File

@@ -51,7 +51,8 @@ class MultistreamHolderMock implements MultistreamHolder {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
io.emeraldpay.dshackle.upstream.starknet.StarknetChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()) io.emeraldpay.dshackle.upstream.starknet.StarknetChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()),
null, Schedulers.immediate()
) )
upstreams[chain].addUpstream(up) upstreams[chain].addUpstream(up)
} else { } else {
@@ -104,7 +105,7 @@ class MultistreamHolderMock implements MultistreamHolder {
super(chain, Schedulers.immediate(), null, upstreams, caches, Schedulers.boundedElastic(), super(chain, Schedulers.immediate(), null, upstreams, caches, Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(new BraveTracer(null, null, null)), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(new BraveTracer(null, null, null)),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
} }
EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<GenericUpstream> upstreams) { EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<GenericUpstream> upstreams) {

View File

@@ -98,6 +98,8 @@ class TestingCommons {
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()),
null,
Schedulers.immediate()
).tap { ).tap {
it.processUpstreamsEvents( it.processUpstreamsEvents(
new UpstreamChangeEvent(Chain.ETHEREUM__MAINNET, up, UpstreamChangeEvent.ChangeType.ADDED) new UpstreamChangeEvent(Chain.ETHEREUM__MAINNET, up, UpstreamChangeEvent.ChangeType.ADDED)
@@ -124,14 +126,18 @@ class TestingCommons {
return new GenericMultistream(chain, Schedulers.immediate(), null, [], emptyCaches().getCaches(chain), Schedulers.boundedElastic(), return new GenericMultistream(chain, Schedulers.immediate(), null, [], emptyCaches().getCaches(chain), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()),
null,
Schedulers.immediate())
} }
static Multistream multistreamClassicWithoutUpstreams(Chain chain) { static Multistream multistreamClassicWithoutUpstreams(Chain chain) {
return new GenericMultistream(chain, Schedulers.immediate(), null, [], emptyCaches().getCaches(chain), Schedulers.boundedElastic(), return new GenericMultistream(chain, Schedulers.immediate(), null, [], emptyCaches().getCaches(chain), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()),
null,
Schedulers.immediate())
} }
static FileResolver fileResolver() { static FileResolver fileResolver() {

View File

@@ -39,7 +39,7 @@ import static java.util.List.of
class FilteredApisSpec extends Specification { class FilteredApisSpec extends Specification {
def ethereumTargets = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def ethereumTargets = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def "Verifies labels"() { def "Verifies labels"() {
setup: setup:

View File

@@ -59,7 +59,7 @@ class MultistreamSpec extends Specification {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
when: when:
aggr.onUpstreamsUpdated() aggr.onUpstreamsUpdated()
def act = aggr.getMethods() def act = aggr.getMethods()
@@ -194,7 +194,7 @@ class MultistreamSpec extends Specification {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
expect: expect:
multistream.getHead(new Selector.LabelMatcher("provider", ["internal"])).is(up1.ethereumHeadMock) multistream.getHead(new Selector.LabelMatcher("provider", ["internal"])).is(up1.ethereumHeadMock)
@@ -267,7 +267,7 @@ class MultistreamSpec extends Specification {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
when: when:
ms.processUpstreamsEvents( ms.processUpstreamsEvents(
new UpstreamChangeEvent(Chain.ETHEREUM__MAINNET, up1, UpstreamChangeEvent.ChangeType.ADDED) new UpstreamChangeEvent(Chain.ETHEREUM__MAINNET, up1, UpstreamChangeEvent.ChangeType.ADDED)
@@ -298,7 +298,7 @@ class MultistreamSpec extends Specification {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
def head1 = createBlock(250, "0x0d050c785de17179f935b9b93aca09c442964cc59972c71ae68e74731448401b") def head1 = createBlock(250, "0x0d050c785de17179f935b9b93aca09c442964cc59972c71ae68e74731448401b")
def head2 = createBlock(270, "0x0d050c785de17179f935b9b93aca09c442964cc59972c71ae68e74731448402b") def head2 = createBlock(270, "0x0d050c785de17179f935b9b93aca09c442964cc59972c71ae68e74731448402b")
def head3 = createBlock(100, "0x0d050c785de17179f935b9b93aca09c442964cc59972c71ae68e74731448412b") def head3 = createBlock(100, "0x0d050c785de17179f935b9b93aca09c442964cc59972c71ae68e74731448412b")
@@ -333,7 +333,7 @@ class MultistreamSpec extends Specification {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) EthereumChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
multistream.processUpstreamsEvents( multistream.processUpstreamsEvents(
new UpstreamChangeEvent(Chain.ETHEREUM__MAINNET, up1, UpstreamChangeEvent.ChangeType.ADDED) new UpstreamChangeEvent(Chain.ETHEREUM__MAINNET, up1, UpstreamChangeEvent.ChangeType.ADDED)
) )
@@ -371,7 +371,7 @@ class MultistreamSpec extends Specification {
Schedulers.boundedElastic(), Schedulers.boundedElastic(),
EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()), EthereumChainSpecific.INSTANCE.makeCachingReaderBuilder(TestingCommons.tracerMock()),
EthereumChainSpecific.INSTANCE.&localReaderBuilder, EthereumChainSpecific.INSTANCE.&localReaderBuilder,
StarknetChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic())) StarknetChainSpecific.INSTANCE.subscriptionBuilder(Schedulers.boundedElastic()), null, Schedulers.immediate())
} }
@NotNull @NotNull

View File

@@ -7,7 +7,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "eth_chainId is available"() { def "eth_chainId is available"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
when: when:
def act = methods.isAvailable("eth_chainId") def act = methods.isAvailable("eth_chainId")
then: then:
@@ -16,7 +16,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "eth_chainId is hardcoded"() { def "eth_chainId is hardcoded"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
when: when:
def act = methods.isHardcoded("eth_chainId") def act = methods.isHardcoded("eth_chainId")
then: then:
@@ -25,7 +25,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "eth_chainId is not callable"() { def "eth_chainId is not callable"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
when: when:
def act = methods.isCallable("eth_chainId") def act = methods.isCallable("eth_chainId")
then: then:
@@ -34,7 +34,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "Provides hardcoded correct chainId"() { def "Provides hardcoded correct chainId"() {
expect: expect:
new String(new DefaultEthereumMethods(chain).executeHardcoded("eth_chainId")) == id new String(new DefaultEthereumMethods(chain, false).executeHardcoded("eth_chainId")) == id
where: where:
chain | id chain | id
Chain.ETHEREUM__MAINNET | '"0x1"' Chain.ETHEREUM__MAINNET | '"0x1"'
@@ -44,7 +44,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "Optimism chain unsupported methods"() { def "Optimism chain unsupported methods"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.OPTIMISM__MAINNET) def methods = new DefaultEthereumMethods(Chain.OPTIMISM__MAINNET, false)
when: when:
def acc = methods.isAvailable("eth_getAccounts") def acc = methods.isAvailable("eth_getAccounts")
def trans = methods.isAvailable("eth_sendTransaction") def trans = methods.isAvailable("eth_sendTransaction")
@@ -55,7 +55,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "Has supported specific methods"() { def "Has supported specific methods"() {
expect: expect:
new DefaultEthereumMethods(chain).getSupportedMethods().containsAll(methods) new DefaultEthereumMethods(chain, false).getSupportedMethods().containsAll(methods)
where: where:
chain | methods chain | methods
Chain.POLYGON__MAINNET | ["bor_getAuthor", Chain.POLYGON__MAINNET | ["bor_getAuthor",
@@ -69,7 +69,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "Has no filter methods by default"() { def "Has no filter methods by default"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
when: when:
def act = methods.getSupportedMethods().findAll { it.containsIgnoreCase("filter") } def act = methods.getSupportedMethods().findAll { it.containsIgnoreCase("filter") }
then: then:
@@ -78,7 +78,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "Has no trace methods by default"() { def "Has no trace methods by default"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
when: when:
def act = methods.getSupportedMethods().findAll { it.containsIgnoreCase("trace") } def act = methods.getSupportedMethods().findAll { it.containsIgnoreCase("trace") }
then: then:
@@ -87,7 +87,7 @@ class DefaultEthereumMethodsSpec extends Specification {
def "Default eth methods are available"() { def "Default eth methods are available"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
expect: expect:
methods.isAvailable(method) methods.isAvailable(method)
where: where:

View File

@@ -94,7 +94,7 @@ class ManagedCallMethodsSpec extends Specification {
def "Use custom quorum if provided"() { def "Use custom quorum if provided"() {
setup: setup:
def managed = new ManagedCallMethods( def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["eth_test", "eth_foo", "eth_bar"] as Set, ["eth_test", "eth_foo", "eth_bar"] as Set,
[] as Set, [] as Set,
[] as Set, [] as Set,
@@ -120,7 +120,7 @@ class ManagedCallMethodsSpec extends Specification {
def "Doesn't reuse same instance"() { def "Doesn't reuse same instance"() {
def managed = new ManagedCallMethods( def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["eth_test"] as Set, ["eth_test"] as Set,
[] as Set, [] as Set,
[] as Set, [] as Set,
@@ -145,7 +145,7 @@ class ManagedCallMethodsSpec extends Specification {
def "Test enable method group"() { def "Test enable method group"() {
setup: setup:
def managed = new ManagedCallMethods( def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
[] as Set, [] as Set,
[] as Set, [] as Set,
["filter"] as Set, ["filter"] as Set,
@@ -169,7 +169,7 @@ class ManagedCallMethodsSpec extends Specification {
def "Test enable method group minus one"() { def "Test enable method group minus one"() {
setup: setup:
def managed = new ManagedCallMethods( def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
[] as Set, [] as Set,
["eth_newPendingTransactionFilter"] as Set, ["eth_newPendingTransactionFilter"] as Set,
["filter"] as Set, ["filter"] as Set,
@@ -193,7 +193,7 @@ class ManagedCallMethodsSpec extends Specification {
def "Test disabled group not disable enabled method"() { def "Test disabled group not disable enabled method"() {
setup: setup:
def managed = new ManagedCallMethods( def managed = new ManagedCallMethods(
new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET), new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false),
["eth_newPendingTransactionFilter"] as Set, ["eth_newPendingTransactionFilter"] as Set,
[] as Set, [] as Set,
[] as Set, [] as Set,

View File

@@ -43,7 +43,7 @@ class EthereumDirectReaderSpec extends Specification {
transactions = [] transactions = []
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -70,7 +70,7 @@ class EthereumDirectReaderSpec extends Specification {
def "Produce empty result on non-existing block"() { def "Produce empty result on non-existing block"() {
setup: setup:
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -103,7 +103,7 @@ class EthereumDirectReaderSpec extends Specification {
transactions = [] transactions = []
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -136,7 +136,7 @@ class EthereumDirectReaderSpec extends Specification {
blockHash = BlockHash.from(hash1) blockHash = BlockHash.from(hash1)
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -169,7 +169,7 @@ class EthereumDirectReaderSpec extends Specification {
blockHash = BlockHash.from(hash1) blockHash = BlockHash.from(hash1)
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -199,7 +199,7 @@ class EthereumDirectReaderSpec extends Specification {
blockHash = BlockHash.from(hash1) blockHash = BlockHash.from(hash1)
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
def caches = Mock(Caches) { def caches = Mock(Caches) {
// note that the Caches needs a Height value, otherwise it's not cached // note that the Caches needs a Height value, otherwise it's not cached
@@ -228,7 +228,7 @@ class EthereumDirectReaderSpec extends Specification {
def "Produce empty on non-existing tx"() { def "Produce empty on non-existing tx"() {
setup: setup:
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() Stub(Multistream), Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -258,7 +258,7 @@ class EthereumDirectReaderSpec extends Specification {
} }
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
up, Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() up, Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -289,7 +289,7 @@ class EthereumDirectReaderSpec extends Specification {
} }
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 1 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
up, Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() up, Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()
@@ -323,7 +323,7 @@ class EthereumDirectReaderSpec extends Specification {
transactions = [] transactions = []
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
3 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 3 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
def result = Mono.just( def result = Mono.just(
new RpcReader.Result( new RpcReader.Result(
@@ -363,7 +363,7 @@ class EthereumDirectReaderSpec extends Specification {
transactions = [] transactions = []
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
3 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 3 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
def result = Mono.just( def result = Mono.just(
new RpcReader.Result( new RpcReader.Result(
@@ -400,7 +400,7 @@ class EthereumDirectReaderSpec extends Specification {
} }
} }
def calls = Mock(Factory) { def calls = Mock(Factory) {
4 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) 4 * create() >> new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
} }
EthereumDirectReader reader = new EthereumDirectReader( EthereumDirectReader reader = new EthereumDirectReader(
up, Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock() up, Caches.default(), new CurrentBlockCache(), calls, TestingCommons.tracerMock()

View File

@@ -21,16 +21,17 @@ class EthereumLocalReaderSpec extends Specification {
def "Calls hardcoded"() { def "Calls hardcoded"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def router = new EthereumLocalReader( def router = new EthereumLocalReader(
new EthereumCachingReader( new EthereumCachingReader(
TestingCommons.multistream(TestingCommons.api()), TestingCommons.multistream(TestingCommons.api()),
Caches.default(), Caches.default(),
ConstantFactory.constantFactory(new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET)), ConstantFactory.constantFactory(new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)),
TestingCommons.tracerMock() TestingCommons.tracerMock()
), ),
methods, methods,
new EmptyHead() new EmptyHead(),
null
) )
when: when:
def act = router.read(new JsonRpcRequest("eth_coinbase", [])).block(Duration.ofSeconds(1)) def act = router.read(new JsonRpcRequest("eth_coinbase", [])).block(Duration.ofSeconds(1))
@@ -40,16 +41,17 @@ class EthereumLocalReaderSpec extends Specification {
def "Returns empty if nonce set"() { def "Returns empty if nonce set"() {
setup: setup:
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def router = new EthereumLocalReader( def router = new EthereumLocalReader(
new EthereumCachingReader( new EthereumCachingReader(
TestingCommons.multistream(TestingCommons.api()), TestingCommons.multistream(TestingCommons.api()),
Caches.default(), Caches.default(),
ConstantFactory.constantFactory(new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET)), ConstantFactory.constantFactory(new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)),
TestingCommons.tracerMock() TestingCommons.tracerMock()
), ),
methods, methods,
new EmptyHead() new EmptyHead(),
null
) )
when: when:
def act = router.read(new JsonRpcRequest("eth_getTransactionByHash", ["test"], 10)) def act = router.read(new JsonRpcRequest("eth_getTransactionByHash", ["test"], 10))
@@ -72,8 +74,8 @@ class EthereumLocalReaderSpec extends Specification {
) )
} }
} }
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def router = new EthereumLocalReader(reader, methods, head) def router = new EthereumLocalReader(reader, methods, head, null)
when: when:
def act = router.getBlockByNumber(["latest", false]) def act = router.getBlockByNumber(["latest", false])
@@ -100,8 +102,8 @@ class EthereumLocalReaderSpec extends Specification {
) )
} }
} }
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def router = new EthereumLocalReader(reader, methods, head) def router = new EthereumLocalReader(reader, methods, head, null)
when: when:
def act = router.getBlockByNumber(["earliest", false]) def act = router.getBlockByNumber(["earliest", false])
@@ -128,8 +130,8 @@ class EthereumLocalReaderSpec extends Specification {
) )
} }
} }
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def router = new EthereumLocalReader(reader, methods, head) def router = new EthereumLocalReader(reader, methods, head, null)
when: when:
def act = router.getBlockByNumber(["0x123ef", false]) def act = router.getBlockByNumber(["0x123ef", false])
@@ -152,8 +154,8 @@ class EthereumLocalReaderSpec extends Specification {
_ * txByHashAsCont() >> new EmptyReader<>() _ * txByHashAsCont() >> new EmptyReader<>()
_ * blocksByHeightAsCont() >> new EmptyReader<>() _ * blocksByHeightAsCont() >> new EmptyReader<>()
} }
def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET) def methods = new DefaultEthereumMethods(Chain.ETHEREUM__MAINNET, false)
def router = new EthereumLocalReader(reader, methods, head) def router = new EthereumLocalReader(reader, methods, head, null)
when: when:
def act = router.getBlockByNumber(["0x0", true]) def act = router.getBlockByNumber(["0x0", true])

View File

@@ -179,6 +179,8 @@ class ReloadConfigTest {
cs.makeCachingReaderBuilder(mock<Tracer>()), cs.makeCachingReaderBuilder(mock<Tracer>()),
cs::localReaderBuilder, cs::localReaderBuilder,
cs.subscriptionBuilder(Schedulers.boundedElastic()), cs.subscriptionBuilder(Schedulers.boundedElastic()),
null,
Schedulers.fromExecutor(Executors.newFixedThreadPool(6)),
) )
} }