add grpc support for PoS Ethereum

This commit is contained in:
terminal
2022-07-29 17:42:19 +04:00
parent eb95c591f7
commit 1df7221c68
24 changed files with 302 additions and 230 deletions

View File

@@ -102,6 +102,7 @@ open class UpstreamsConfig {
var host: String? = null var host: String? = null
var port: Int = 0 var port: Int = 0
var auth: AuthConfig.ClientTlsAuth? = null var auth: AuthConfig.ClientTlsAuth? = null
var nodeRating: Int = 0
} }
class EthereumConnection : RpcConnection() { class EthereumConnection : RpcConnection() {

View File

@@ -106,6 +106,9 @@ class UpstreamsConfigReader(
config.upstreams.add(upstream) config.upstreams.add(upstream)
val connection = UpstreamsConfig.GrpcConnection() val connection = UpstreamsConfig.GrpcConnection()
upstream.connection = connection upstream.connection = connection
getValueAsInt(connConfigNode, "node-rating")?.let {
connection.nodeRating = it
}
getValueAsString(connConfigNode, "host")?.let { getValueAsString(connConfigNode, "host")?.let {
connection.host = it connection.host = it
} }

View File

@@ -29,8 +29,8 @@ import io.emeraldpay.dshackle.upstream.bitcoin.ExtractBlock
import io.emeraldpay.dshackle.upstream.bitcoin.ZMQServer import io.emeraldpay.dshackle.upstream.bitcoin.ZMQServer
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosRpcUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWsFactory import io.emeraldpay.dshackle.upstream.ethereum.EthereumWsFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory
import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.ForkChoice
@@ -160,7 +160,7 @@ open class ConfiguredUpstreams(
if (connectorFactory == null) { if (connectorFactory == null) {
return null return null
} }
val upstream = EthereumPosUpstream( val upstream = EthereumPosRpcUpstream(
config.id!!, config.id!!,
chain, chain,
options, config.role, options, config.role,
@@ -218,7 +218,7 @@ open class ConfiguredUpstreams(
config: UpstreamsConfig.Upstream<UpstreamsConfig.EthereumConnection>, config: UpstreamsConfig.Upstream<UpstreamsConfig.EthereumConnection>,
chain: Chain, chain: Chain,
options: UpstreamsConfig.Options options: UpstreamsConfig.Options
) : EthereumUpstream? { ) : EthereumRpcUpstream? {
val conn = config.connection!! val conn = config.connection!!
val urls = ArrayList<URI>() val urls = ArrayList<URI>()
@@ -228,7 +228,7 @@ open class ConfiguredUpstreams(
if (connectorFactory == null) { if (connectorFactory == null) {
return null return null
} }
val upstream = EthereumUpstream( val upstream = EthereumRpcUpstream(
config.id!!, config.id!!,
chain, chain,
options, config.role, options, config.role,
@@ -251,7 +251,8 @@ open class ConfiguredUpstreams(
endpoint.host!!, endpoint.host!!,
endpoint.port, endpoint.port,
endpoint.auth, endpoint.auth,
fileResolver fileResolver,
endpoint.nodeRating
).apply { ).apply {
timeout = options.timeout timeout = options.timeout
} }

View File

@@ -24,10 +24,7 @@ import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinUpstream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream import io.emeraldpay.dshackle.upstream.ethereum.*
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.grpc.BlockchainType import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory

View File

@@ -49,7 +49,7 @@ open class ERC20Balance {
apis.request(1) apis.request(1)
return Flux.from(apis) return Flux.from(apis)
.flatMap { .flatMap {
getBalance(it.cast(EthereumUpstream::class.java), token, address) getBalance(it.cast(EthereumRpcUpstream::class.java), token, address)
} }
.doOnNext { .doOnNext {
apis.resolve() apis.resolve()
@@ -57,7 +57,7 @@ open class ERC20Balance {
.next() .next()
} }
open fun getBalance(upstream: EthereumUpstream, token: ERC20Token, address: Address): Mono<BigInteger> { open fun getBalance(upstream: EthereumRpcUpstream, token: ERC20Token, address: Address): Mono<BigInteger> {
return upstream return upstream
.getApi() .getApi()
.read(prepareEthCall(token, address, upstream.getHead())) .read(prepareEthCall(token, address, upstream.getHead()))

View File

@@ -0,0 +1,98 @@
/**
* Copyright (c) 2020 EmeraldPay, Inc
* Copyright (c) 2019 ETCDEV GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.ethereum.connectors.ConnectorFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable
open class EthereumRpcUpstream(
id: String,
val chain: Chain,
options: UpstreamsConfig.Options,
role: UpstreamsConfig.UpstreamRole,
targets: CallMethods?,
private val node: QuorumForLabels.QuorumItem?,
connectorFactory: ConnectorFactory
) : EthereumUpstream(id, options, role, targets, node), Lifecycle, Upstream, CachesEnabled {
private val log = LoggerFactory.getLogger(EthereumRpcUpstream::class.java)
private val validator : EthereumUpstreamValidator = EthereumUpstreamValidator(this, getOptions())
private val connector : EthereumConnector = connectorFactory.create(this, validator, chain)
private var validatorSubscription: Disposable? = null
override fun setCaches(caches: Caches) {
if (connector is CachesEnabled) {
connector.setCaches(caches)
}
}
override fun start() {
log.info("Configured for ${chain.chainName}")
connector.start()
if (getOptions().disableValidation != null && getOptions().disableValidation!!) {
log.warn("Disable validation for upstream ${this.getId()}")
this.setLag(0)
this.setStatus(UpstreamAvailability.OK)
} else {
log.debug("Start validation for upstream ${this.getId()}")
validatorSubscription = validator.start()
.subscribe(this::setStatus)
}
}
override fun getHead(): Head {
return connector.getHead()
}
override fun stop() {
validatorSubscription?.dispose()
validatorSubscription = null
connector.stop()
}
override fun isRunning(): Boolean {
return connector.isRunning
}
override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> {
return connector.getApi()
}
override fun isGrpc(): Boolean {
return false
}
@Suppress("UNCHECKED_CAST")
override fun <T : Upstream> cast(selfType: Class<T>): T {
if (!selfType.isAssignableFrom(this.javaClass)) {
throw ClassCastException("Cannot cast ${this.javaClass} to $selfType")
}
return this as T
}
}

View File

@@ -16,78 +16,19 @@
*/ */
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.* import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.ethereum.connectors.ConnectorFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable
open class EthereumUpstream( abstract class EthereumUpstream(
id: String, id: String,
val chain: Chain,
options: UpstreamsConfig.Options, options: UpstreamsConfig.Options,
role: UpstreamsConfig.UpstreamRole, role: UpstreamsConfig.UpstreamRole,
targets: CallMethods?, targets: CallMethods?,
private val node: QuorumForLabels.QuorumItem?, private val node: QuorumForLabels.QuorumItem?
connectorFactory: ConnectorFactory ) : DefaultUpstream(id, options, role, targets, node) {
) : DefaultUpstream(id, options, role, targets, node), Lifecycle, Upstream, CachesEnabled {
private val log = LoggerFactory.getLogger(EthereumUpstream::class.java)
private val validator : EthereumUpstreamValidator = EthereumUpstreamValidator(this, getOptions())
private val connector : EthereumConnector = connectorFactory.create(this, validator, chain)
private var validatorSubscription: Disposable? = null
override fun setCaches(caches: Caches) {
if (connector is CachesEnabled) {
connector.setCaches(caches)
}
}
override fun start() {
log.info("Configured for ${chain.chainName}")
connector.start()
if (getOptions().disableValidation != null && getOptions().disableValidation!!) {
log.warn("Disable validation for upstream ${this.getId()}")
this.setLag(0)
this.setStatus(UpstreamAvailability.OK)
} else {
log.debug("Start validation for upstream ${this.getId()}")
validatorSubscription = validator.start()
.subscribe(this::setStatus)
}
}
override fun getHead(): Head {
return connector.getHead()
}
override fun stop() {
validatorSubscription?.dispose()
validatorSubscription = null
connector.stop()
}
override fun isRunning(): Boolean {
return connector.isRunning
}
override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> {
return connector.getApi()
}
override fun isGrpc(): Boolean {
return false
}
private val capabilities = if (options.providesBalance != false) { private val capabilities = if (options.providesBalance != false) {
setOf(Capability.RPC, Capability.BALANCE) setOf(Capability.RPC, Capability.BALANCE)
@@ -102,12 +43,4 @@ open class EthereumUpstream(
override fun getLabels(): Collection<UpstreamsConfig.Labels> { override fun getLabels(): Collection<UpstreamsConfig.Labels> {
return node?.let { listOf(it.labels) } ?: emptyList() return node?.let { listOf(it.labels) } ?: emptyList()
} }
}
@Suppress("UNCHECKED_CAST")
override fun <T : Upstream> cast(selfType: Class<T>): T {
if (!selfType.isAssignableFrom(this.javaClass)) {
throw ClassCastException("Cannot cast ${this.javaClass} to $selfType")
}
return this as T
}
}

View File

@@ -25,7 +25,6 @@ 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
import io.emeraldpay.dshackle.upstream.Upstream import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.dshackle.upstream.forkchoice.PriorityForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.PriorityForkChoice
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

View File

@@ -0,0 +1,98 @@
/**
* Copyright (c) 2020 EmeraldPay, Inc
* Copyright (c) 2019 ETCDEV GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.ethereum.connectors.ConnectorFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable
open class EthereumPosRpcUpstream(
id: String,
val chain: Chain,
options: UpstreamsConfig.Options,
role: UpstreamsConfig.UpstreamRole,
targets: CallMethods?,
private val node: QuorumForLabels.QuorumItem?,
connectorFactory: ConnectorFactory
) : EthereumPosUpstream(id, options, role, targets, node), Lifecycle, Upstream, CachesEnabled {
private val log = LoggerFactory.getLogger(EthereumPosRpcUpstream::class.java)
private val validator : EthereumUpstreamValidator = EthereumUpstreamValidator(this, getOptions())
private val connector : EthereumConnector = connectorFactory.create(this, validator, chain)
private var validatorSubscription: Disposable? = null
override fun setCaches(caches: Caches) {
if (connector is CachesEnabled) {
connector.setCaches(caches)
}
}
override fun start() {
log.info("Configured for ${chain.chainName}")
connector.start()
if (getOptions().disableValidation != null && getOptions().disableValidation!!) {
log.warn("Disable validation for upstream ${this.getId()}")
this.setLag(0)
this.setStatus(UpstreamAvailability.OK)
} else {
log.debug("Start validation for upstream ${this.getId()}")
validatorSubscription = validator.start()
.subscribe(this::setStatus)
}
}
override fun getHead(): Head {
return connector.getHead()
}
override fun stop() {
validatorSubscription?.dispose()
validatorSubscription = null
connector.stop()
}
override fun isRunning(): Boolean {
return connector.isRunning
}
override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> {
return connector.getApi()
}
override fun isGrpc(): Boolean {
return false
}
@Suppress("UNCHECKED_CAST")
override fun <T : Upstream> cast(selfType: Class<T>): T {
if (!selfType.isAssignableFrom(this.javaClass)) {
throw ClassCastException("Cannot cast ${this.javaClass} to $selfType")
}
return this as T
}
}

View File

@@ -16,78 +16,19 @@
*/ */
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.* import io.emeraldpay.dshackle.upstream.Capability
import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.ethereum.connectors.ConnectorFactory
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnector
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.grpc.Chain
import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable
open class EthereumPosUpstream( abstract class EthereumPosUpstream(
id: String, id: String,
val chain: Chain,
options: UpstreamsConfig.Options, options: UpstreamsConfig.Options,
role: UpstreamsConfig.UpstreamRole, role: UpstreamsConfig.UpstreamRole,
targets: CallMethods?, targets: CallMethods?,
private val node: QuorumForLabels.QuorumItem?, private val node: QuorumForLabels.QuorumItem?
connectorFactory: ConnectorFactory ) : DefaultUpstream(id, options, role, targets, node) {
) : DefaultUpstream(id, options, role, targets, node), Lifecycle, Upstream, CachesEnabled {
private val log = LoggerFactory.getLogger(EthereumPosUpstream::class.java)
private val validator : EthereumUpstreamValidator = EthereumUpstreamValidator(this, getOptions())
private val connector : EthereumConnector = connectorFactory.create(this, validator, chain)
private var validatorSubscription: Disposable? = null
override fun setCaches(caches: Caches) {
if (connector is CachesEnabled) {
connector.setCaches(caches)
}
}
override fun start() {
log.info("Configured for ${chain.chainName}")
connector.start()
if (getOptions().disableValidation != null && getOptions().disableValidation!!) {
log.warn("Disable validation for upstream ${this.getId()}")
this.setLag(0)
this.setStatus(UpstreamAvailability.OK)
} else {
log.debug("Start validation for upstream ${this.getId()}")
validatorSubscription = validator.start()
.subscribe(this::setStatus)
}
}
override fun getHead(): Head {
return connector.getHead()
}
override fun stop() {
validatorSubscription?.dispose()
validatorSubscription = null
connector.stop()
}
override fun isRunning(): Boolean {
return connector.isRunning
}
override fun getApi(): Reader<JsonRpcRequest, JsonRpcResponse> {
return connector.getApi()
}
override fun isGrpc(): Boolean {
return false
}
private val capabilities = if (options.providesBalance != false) { private val capabilities = if (options.providesBalance != false) {
setOf(Capability.RPC, Capability.BALANCE) setOf(Capability.RPC, Capability.BALANCE)
@@ -102,12 +43,4 @@ open class EthereumPosUpstream(
override fun getLabels(): Collection<UpstreamsConfig.Labels> { override fun getLabels(): Collection<UpstreamsConfig.Labels> {
return node?.let { listOf(it.labels) } ?: emptyList() return node?.let { listOf(it.labels) } ?: emptyList()
} }
}
@Suppress("UNCHECKED_CAST")
override fun <T : Upstream> cast(selfType: Class<T>): T {
if (!selfType.isAssignableFrom(this.javaClass)) {
throw ClassCastException("Cannot cast ${this.javaClass} to $selfType")
}
return this as T
}
}

View File

@@ -50,7 +50,7 @@ open class EthereumGrpcUpstream(
private val chain: Chain, private val chain: Chain,
private val remote: ReactorBlockchainGrpc.ReactorBlockchainStub, private val remote: ReactorBlockchainGrpc.ReactorBlockchainStub,
private val client: JsonRpcGrpcClient private val client: JsonRpcGrpcClient
) : DefaultUpstream( ) : EthereumUpstream(
"${parentId}_${chain.chainCode.lowercase(Locale.getDefault())}", "${parentId}_${chain.chainCode.lowercase(Locale.getDefault())}",
UpstreamsConfig.Options.getDefaults(), UpstreamsConfig.Options.getDefaults(),
role, role,

View File

@@ -26,8 +26,8 @@ import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.startup.QuorumForLabels import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.* import io.emeraldpay.dshackle.upstream.*
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosUpstream
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.NoChoiceWithPriorityForkChoice
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient
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
@@ -48,9 +48,10 @@ open class EthereumPosGrpcUpstream(
private val parentId: String, private val parentId: String,
role: UpstreamsConfig.UpstreamRole, role: UpstreamsConfig.UpstreamRole,
private val chain: Chain, private val chain: Chain,
private val remote: ReactorBlockchainGrpc.ReactorBlockchainStub, remote: ReactorBlockchainGrpc.ReactorBlockchainStub,
private val client: JsonRpcGrpcClient client: JsonRpcGrpcClient,
) : DefaultUpstream( nodeRating: Int
) : EthereumPosUpstream(
"${parentId}_${chain.chainCode.lowercase(Locale.getDefault())}", "${parentId}_${chain.chainCode.lowercase(Locale.getDefault())}",
UpstreamsConfig.Options.getDefaults(), UpstreamsConfig.Options.getDefaults(),
role, role,
@@ -94,7 +95,7 @@ open class EthereumPosGrpcUpstream(
private val log = LoggerFactory.getLogger(EthereumGrpcUpstream::class.java) private val log = LoggerFactory.getLogger(EthereumGrpcUpstream::class.java)
private val upstreamStatus = GrpcUpstreamStatus() private val upstreamStatus = GrpcUpstreamStatus()
private val grpcHead = GrpcHead(chain, this, remote, blockConverter, reloadBlock, MostWorkForkChoice()) private val grpcHead = GrpcHead(chain, this, remote, blockConverter, reloadBlock, NoChoiceWithPriorityForkChoice(nodeRating))
private var capabilities: Set<Capability> = emptySet() private var capabilities: Set<Capability> = emptySet()
private val defaultReader: Reader<JsonRpcRequest, JsonRpcResponse> = client.forSelector(Selector.empty) private val defaultReader: Reader<JsonRpcRequest, JsonRpcResponse> = client.forSelector(Selector.empty)

View File

@@ -56,7 +56,8 @@ class GrpcUpstreams(
private val host: String, private val host: String,
private val port: Int, private val port: Int,
private val auth: AuthConfig.ClientTlsAuth? = null, private val auth: AuthConfig.ClientTlsAuth? = null,
private val fileResolver: FileResolver private val fileResolver: FileResolver,
private val nodeRating: Int
) { ) {
private val log = LoggerFactory.getLogger(GrpcUpstreams::class.java) private val log = LoggerFactory.getLogger(GrpcUpstreams::class.java)
@@ -192,6 +193,8 @@ class GrpcUpstreams(
return getOrCreateEthereum(chain, metrics) return getOrCreateEthereum(chain, metrics)
} else if (blockchainType == BlockchainType.BITCOIN) { } else if (blockchainType == BlockchainType.BITCOIN) {
return getOrCreateBitcoin(chain, metrics) return getOrCreateBitcoin(chain, metrics)
} else if (blockchainType == BlockchainType.ETHEREUM_POS) {
return getOrCreateEthereumPos(chain, metrics)
} else { } else {
throw IllegalArgumentException("Unsupported blockchain: $chain") throw IllegalArgumentException("Unsupported blockchain: $chain")
} }
@@ -213,6 +216,22 @@ class GrpcUpstreams(
} }
} }
fun getOrCreateEthereumPos(chain: Chain, metrics: RpcMetrics): UpstreamChange {
lock.withLock {
val current = known[chain]
return if (current == null) {
val rpcClient = JsonRpcGrpcClient(client!!, chain, metrics)
val created = EthereumPosGrpcUpstream(id, role, chain, client!!, rpcClient, nodeRating)
created.timeout = this.timeout
known[chain] = created
created.start()
UpstreamChange(chain, created, UpstreamChange.ChangeType.ADDED)
} else {
UpstreamChange(chain, current, UpstreamChange.ChangeType.REVALIDATED)
}
}
}
fun getOrCreateBitcoin(chain: Chain, metrics: RpcMetrics): UpstreamChange { fun getOrCreateBitcoin(chain: Chain, metrics: RpcMetrics): UpstreamChange {
lock.withLock { lock.withLock {
val current = known[chain] val current = known[chain]

View File

@@ -17,9 +17,6 @@
package io.emeraldpay.dshackle.config package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.grpc.Chain
import io.emeraldpay.etherjar.rpc.RpcClient
import spock.lang.Specification import spock.lang.Specification
class UpstreamsConfigReaderSpec extends Specification { class UpstreamsConfigReaderSpec extends Specification {

View File

@@ -22,10 +22,10 @@ import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.data.BlockContainer import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.test.EthereumUpstreamMock import io.emeraldpay.dshackle.test.EthereumRpcUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.test.MultistreamHolderMock import io.emeraldpay.dshackle.test.MultistreamHolderMock
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
import io.emeraldpay.grpc.Chain import io.emeraldpay.grpc.Chain
import io.emeraldpay.etherjar.domain.BlockHash import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson import io.emeraldpay.etherjar.rpc.json.BlockJson
@@ -43,7 +43,7 @@ class StreamHeadSpec extends Specification {
def "Errors on unavailable chain"() { def "Errors on unavailable chain"() {
setup: setup:
def upstreams = new MultistreamHolderMock(Chain.ETHEREUM, Stub(EthereumUpstream)) def upstreams = new MultistreamHolderMock(Chain.ETHEREUM, Stub(EthereumRpcUpstream))
def streamHead = new StreamHead(upstreams) def streamHead = new StreamHead(upstreams)
when: when:
def flux = streamHead.add( def flux = streamHead.add(
@@ -78,7 +78,7 @@ class StreamHeadSpec extends Specification {
.build() .build()
} }
def upstream = new EthereumUpstreamMock(Chain.ETHEREUM, TestingCommons.api()) def upstream = new EthereumRpcUpstreamMock(Chain.ETHEREUM, TestingCommons.api())
def upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstream) def upstreams = new MultistreamHolderMock(Chain.ETHEREUM, upstream)
def streamHead = new StreamHead(upstreams) def streamHead = new StreamHead(upstreams)
when: when:

View File

@@ -3,18 +3,12 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.config.TokensConfig import io.emeraldpay.dshackle.config.TokensConfig
import io.emeraldpay.dshackle.test.EthereumUpstreamMock
import io.emeraldpay.dshackle.test.MultistreamHolderMock
import io.emeraldpay.dshackle.test.ReaderMock
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.ethereum.ERC20Balance import io.emeraldpay.dshackle.upstream.ethereum.ERC20Balance
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumSubscribe import io.emeraldpay.dshackle.upstream.ethereum.EthereumSubscribe
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.dshackle.upstream.ethereum.subscribe.ConnectLogs import io.emeraldpay.dshackle.upstream.ethereum.subscribe.ConnectLogs
import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.LogMessage import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.LogMessage
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.domain.BlockHash import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId import io.emeraldpay.etherjar.domain.TransactionId
import io.emeraldpay.etherjar.hex.Hex32 import io.emeraldpay.etherjar.hex.Hex32
@@ -22,11 +16,9 @@ import io.emeraldpay.grpc.Chain
import io.emeraldpay.etherjar.domain.Address import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.erc20.ERC20Token import io.emeraldpay.etherjar.erc20.ERC20Token
import io.emeraldpay.etherjar.hex.HexData import io.emeraldpay.etherjar.hex.HexData
import io.emeraldpay.etherjar.rpc.json.TransactionCallJson
import reactor.core.publisher.Flux import reactor.core.publisher.Flux
import reactor.core.publisher.Mono import reactor.core.publisher.Mono
import reactor.test.StepVerifier import reactor.test.StepVerifier
import spock.lang.Ignore
import spock.lang.Specification import spock.lang.Specification
import java.time.Duration import java.time.Duration

View File

@@ -25,7 +25,7 @@ import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods import io.emeraldpay.dshackle.upstream.calls.DefaultBitcoinMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability import io.emeraldpay.dshackle.upstream.UpstreamAvailability
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
@@ -35,7 +35,7 @@ import org.jetbrains.annotations.NotNull
import org.reactivestreams.Publisher import org.reactivestreams.Publisher
class EthereumUpstreamMock extends EthereumUpstream { class EthereumRpcUpstreamMock extends EthereumRpcUpstream {
EthereumHeadMock ethereumHeadMock EthereumHeadMock ethereumHeadMock
@@ -47,19 +47,19 @@ class EthereumUpstreamMock extends EthereumUpstream {
]) ])
} }
EthereumUpstreamMock(@NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api) { EthereumRpcUpstreamMock(@NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api) {
this(chain, api, allMethods()) this(chain, api, allMethods())
} }
EthereumUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api) { EthereumRpcUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api) {
this(id, chain, api, allMethods()) this(id, chain, api, allMethods())
} }
EthereumUpstreamMock(@NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api, CallMethods methods) { EthereumRpcUpstreamMock(@NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api, CallMethods methods) {
this("test", chain, api, methods) this("test", chain, api, methods)
} }
EthereumUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api, CallMethods methods) { EthereumRpcUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull Reader<JsonRpcRequest, JsonRpcResponse> api, CallMethods methods) {
super(id, chain, super(id, chain,
UpstreamsConfig.Options.getDefaults(), UpstreamsConfig.Options.getDefaults(),
UpstreamsConfig.UpstreamRole.PRIMARY, UpstreamsConfig.UpstreamRole.PRIMARY,

View File

@@ -28,7 +28,7 @@ import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.MultistreamHolder import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
import io.emeraldpay.grpc.BlockchainType import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain import io.emeraldpay.grpc.Chain
import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.NotNull
@@ -48,8 +48,8 @@ class MultistreamHolderMock implements MultistreamHolder {
if (BlockchainType.from(chain) == BlockchainType.ETHEREUM) { if (BlockchainType.from(chain) == BlockchainType.ETHEREUM) {
if (up instanceof EthereumMultistream) { if (up instanceof EthereumMultistream) {
upstreams[chain] = up upstreams[chain] = up
} else if (up instanceof EthereumUpstream) { } else if (up instanceof EthereumRpcUpstream) {
upstreams[chain] = new EthereumMultistreamMock(chain, [up as EthereumUpstream], Caches.default()) upstreams[chain] = new EthereumMultistreamMock(chain, [up as EthereumRpcUpstream], Caches.default())
} else { } else {
throw new IllegalArgumentException("Unsupported upstream type ${up.class}") throw new IllegalArgumentException("Unsupported upstream type ${up.class}")
} }
@@ -105,15 +105,15 @@ class MultistreamHolderMock implements MultistreamHolder {
CallMethods customMethods = null CallMethods customMethods = null
Head customHead = null Head customHead = null
EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<EthereumUpstream> upstreams, @NotNull Caches caches) { EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<EthereumRpcUpstream> upstreams, @NotNull Caches caches) {
super(chain, upstreams, caches) super(chain, upstreams, caches)
} }
EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<EthereumUpstream> upstreams) { EthereumMultistreamMock(@NotNull Chain chain, @NotNull List<EthereumRpcUpstream> upstreams) {
this(chain, upstreams, Caches.default()) this(chain, upstreams, Caches.default())
} }
EthereumMultistreamMock(@NotNull Chain chain, @NotNull EthereumUpstream upstream) { EthereumMultistreamMock(@NotNull Chain chain, @NotNull EthereumRpcUpstream upstream) {
this(chain, [upstream]) this(chain, [upstream])
} }

View File

@@ -28,7 +28,7 @@ import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
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
import io.emeraldpay.grpc.Chain import io.emeraldpay.grpc.Chain
@@ -46,35 +46,35 @@ class TestingCommons {
return new ApiReaderMock() return new ApiReaderMock()
} }
static EthereumUpstreamMock upstream() { static EthereumRpcUpstreamMock upstream() {
return new EthereumUpstreamMock(Chain.ETHEREUM, api()) return new EthereumRpcUpstreamMock(Chain.ETHEREUM, api())
} }
static EthereumUpstreamMock upstream(String id) { static EthereumRpcUpstreamMock upstream(String id) {
return new EthereumUpstreamMock(id, Chain.ETHEREUM, api()) return new EthereumRpcUpstreamMock(id, Chain.ETHEREUM, api())
} }
static EthereumUpstreamMock upstream(String id, Reader<JsonRpcRequest, JsonRpcResponse> api) { static EthereumRpcUpstreamMock upstream(String id, Reader<JsonRpcRequest, JsonRpcResponse> api) {
return new EthereumUpstreamMock(id, Chain.ETHEREUM, api) return new EthereumRpcUpstreamMock(id, Chain.ETHEREUM, api)
} }
static EthereumUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api) { static EthereumRpcUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api) {
return new EthereumUpstreamMock(Chain.ETHEREUM, api) return new EthereumRpcUpstreamMock(Chain.ETHEREUM, api)
} }
static EthereumUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api, String method) { static EthereumRpcUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api, String method) {
return upstream(api, [method]) return upstream(api, [method])
} }
static EthereumUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api, List<String> methods) { static EthereumRpcUpstreamMock upstream(Reader<JsonRpcRequest, JsonRpcResponse> api, List<String> methods) {
return new EthereumUpstreamMock(Chain.ETHEREUM, api, new DirectCallMethods(methods)) return new EthereumRpcUpstreamMock(Chain.ETHEREUM, api, new DirectCallMethods(methods))
} }
static Multistream multistream(Reader<JsonRpcRequest, JsonRpcResponse> api) { static Multistream multistream(Reader<JsonRpcRequest, JsonRpcResponse> api) {
return multistream(upstream(api)) return multistream(upstream(api))
} }
static Multistream multistream(EthereumUpstream up) { static Multistream multistream(EthereumRpcUpstream up) {
return new EthereumMultistream(Chain.ETHEREUM, [up], Caches.default()).tap { return new EthereumMultistream(Chain.ETHEREUM, [up], Caches.default()).tap {
start() start()
} }

View File

@@ -16,7 +16,7 @@
package io.emeraldpay.dshackle.upstream package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.startup.UpstreamChange import io.emeraldpay.dshackle.startup.UpstreamChange
import io.emeraldpay.dshackle.test.EthereumUpstreamMock import io.emeraldpay.dshackle.test.EthereumRpcUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.grpc.Chain import io.emeraldpay.grpc.Chain
import spock.lang.Specification import spock.lang.Specification
@@ -26,7 +26,7 @@ class CurrentMultistreamHolderSpec extends Specification {
def "add upstream"() { def "add upstream"() {
setup: setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches()) def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def up = new EthereumUpstreamMock("test", Chain.ETHEREUM, TestingCommons.api()) def up = new EthereumRpcUpstreamMock("test", Chain.ETHEREUM, TestingCommons.api())
when: when:
current.update(new UpstreamChange(Chain.ETHEREUM, up, UpstreamChange.ChangeType.ADDED)) current.update(new UpstreamChange(Chain.ETHEREUM, up, UpstreamChange.ChangeType.ADDED))
then: then:
@@ -37,9 +37,9 @@ class CurrentMultistreamHolderSpec extends Specification {
def "add multiple upstreams"() { def "add multiple upstreams"() {
setup: setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches()) def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api()) def up1 = new EthereumRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
def up2 = new EthereumUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api()) def up2 = new EthereumRpcUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
def up3 = new EthereumUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api()) def up3 = new EthereumRpcUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
when: when:
current.update(new UpstreamChange(Chain.ETHEREUM, up1, UpstreamChange.ChangeType.ADDED)) current.update(new UpstreamChange(Chain.ETHEREUM, up1, UpstreamChange.ChangeType.ADDED))
current.update(new UpstreamChange(Chain.ETHEREUM_CLASSIC, up2, UpstreamChange.ChangeType.ADDED)) current.update(new UpstreamChange(Chain.ETHEREUM_CLASSIC, up2, UpstreamChange.ChangeType.ADDED))
@@ -53,10 +53,10 @@ class CurrentMultistreamHolderSpec extends Specification {
def "remove upstream"() { def "remove upstream"() {
setup: setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches()) def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api()) def up1 = new EthereumRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
def up2 = new EthereumUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api()) def up2 = new EthereumRpcUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
def up3 = new EthereumUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api()) def up3 = new EthereumRpcUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
def up1_del = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api()) def up1_del = new EthereumRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
when: when:
current.update(new UpstreamChange(Chain.ETHEREUM, up1, UpstreamChange.ChangeType.ADDED)) current.update(new UpstreamChange(Chain.ETHEREUM, up1, UpstreamChange.ChangeType.ADDED))
current.update(new UpstreamChange(Chain.ETHEREUM_CLASSIC, up2, UpstreamChange.ChangeType.ADDED)) current.update(new UpstreamChange(Chain.ETHEREUM_CLASSIC, up2, UpstreamChange.ChangeType.ADDED))
@@ -71,7 +71,7 @@ class CurrentMultistreamHolderSpec extends Specification {
def "available after adding"() { def "available after adding"() {
setup: setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches()) def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api()) def up1 = new EthereumRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
when: when:
def act = current.isAvailable(Chain.ETHEREUM) def act = current.isAvailable(Chain.ETHEREUM)

View File

@@ -21,7 +21,7 @@ import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.test.EthereumApiStub import io.emeraldpay.dshackle.test.EthereumApiStub
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.grpc.Chain import io.emeraldpay.grpc.Chain
@@ -38,7 +38,7 @@ class FilteredApisSpec extends Specification {
def "Verifies labels"() { def "Verifies labels"() {
setup: setup:
def i = 0 def i = 0
List<EthereumUpstream> upstreams = [ List<EthereumRpcUpstream> upstreams = [
[test: "foo"], [test: "foo"],
[test: "bar"], [test: "bar"],
[test: "foo", test2: "baz"], [test: "foo", test2: "baz"],
@@ -49,7 +49,7 @@ class FilteredApisSpec extends Specification {
create(_, _) >> TestingCommons.api().tap { it.id = "${i++}" } create(_, _) >> TestingCommons.api().tap { it.id = "${i++}" }
} }
def connectorFactory = new EthereumConnectorFactory(false, null, httpFactory, new MostWorkForkChoice()) def connectorFactory = new EthereumConnectorFactory(false, null, httpFactory, new MostWorkForkChoice())
new EthereumUpstream( new EthereumRpcUpstream(
"test", "test",
Chain.ETHEREUM, Chain.ETHEREUM,
new UpstreamsConfig.Options(), new UpstreamsConfig.Options(),

View File

@@ -20,7 +20,7 @@ import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.quorum.AlwaysQuorum import io.emeraldpay.dshackle.quorum.AlwaysQuorum
import io.emeraldpay.dshackle.reader.Reader import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.test.EthereumUpstreamMock import io.emeraldpay.dshackle.test.EthereumRpcUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
@@ -38,8 +38,8 @@ class MultistreamSpec extends Specification {
def "Aggregates methods"() { def "Aggregates methods"() {
setup: setup:
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test1", "eth_test2"])) def up1 = new EthereumRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test1", "eth_test2"]))
def up2 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test2", "eth_test3"])) def up2 = new EthereumRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api(), new DirectCallMethods(["eth_test2", "eth_test3"]))
def aggr = new EthereumMultistream(Chain.ETHEREUM, [up1, up2], Caches.default()) def aggr = new EthereumMultistream(Chain.ETHEREUM, [up1, up2], Caches.default())
when: when:
aggr.onUpstreamsUpdated() aggr.onUpstreamsUpdated()

View File

@@ -15,7 +15,7 @@
*/ */
package io.emeraldpay.dshackle.upstream.ethereum package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.test.EthereumUpstreamMock import io.emeraldpay.dshackle.test.EthereumRpcUpstreamMock
import io.emeraldpay.dshackle.test.ReaderMock import io.emeraldpay.dshackle.test.ReaderMock
import io.emeraldpay.dshackle.upstream.ApiSource import io.emeraldpay.dshackle.upstream.ApiSource
import io.emeraldpay.dshackle.upstream.FilteredApis import io.emeraldpay.dshackle.upstream.FilteredApis
@@ -47,7 +47,7 @@ class ERC20BalanceSpec extends Specification {
JsonRpcResponse.ok('"0x0000000000000000000000000000000000000000000000000000001f28d72868"') JsonRpcResponse.ok('"0x0000000000000000000000000000000000000000000000000000001f28d72868"')
) )
EthereumUpstream upstream = new EthereumUpstreamMock(Chain.ETHEREUM, api) EthereumRpcUpstream upstream = new EthereumRpcUpstreamMock(Chain.ETHEREUM, api)
ERC20Token token = new ERC20Token(Address.from("0x54EedeAC495271d0F6B175474E89094C44Da98b9")) ERC20Token token = new ERC20Token(Address.from("0x54EedeAC495271d0F6B175474E89094C44Da98b9"))
ERC20Balance query = new ERC20Balance() ERC20Balance query = new ERC20Balance()
@@ -73,7 +73,7 @@ class ERC20BalanceSpec extends Specification {
JsonRpcResponse.ok('"0x0000000000000000000000000000000000000000000000000000001f28d72868"') JsonRpcResponse.ok('"0x0000000000000000000000000000000000000000000000000000001f28d72868"')
) )
EthereumUpstream upstream = new EthereumUpstreamMock(Chain.ETHEREUM, api) EthereumRpcUpstream upstream = new EthereumRpcUpstreamMock(Chain.ETHEREUM, api)
ERC20Token token = new ERC20Token(Address.from("0x54EedeAC495271d0F6B175474E89094C44Da98b9")) ERC20Token token = new ERC20Token(Address.from("0x54EedeAC495271d0F6B175474E89094C44Da98b9"))
ERC20Balance query = new ERC20Balance() ERC20Balance query = new ERC20Balance()

View File

@@ -23,7 +23,7 @@ import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxContainer import io.emeraldpay.dshackle.data.TxContainer
import io.emeraldpay.dshackle.data.TxId import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.test.EthereumUpstreamMock import io.emeraldpay.dshackle.test.EthereumRpcUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.Multistream import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.CallMethods import io.emeraldpay.dshackle.upstream.calls.CallMethods
@@ -203,7 +203,7 @@ class EthereumReaderSpec extends Specification {
api.answerOnce("eth_getBalance", ["0x70b91ff87a902b53dc6e2f6bda8bb9b330ccd30c", "latest"], "0x10") api.answerOnce("eth_getBalance", ["0x70b91ff87a902b53dc6e2f6bda8bb9b330ccd30c", "latest"], "0x10")
// height 101 + 1 => 102 => 0x66 // height 101 + 1 => 102 => 0x66
api.answerOnce("eth_getBalance", ["0x70b91ff87a902b53dc6e2f6bda8bb9b330ccd30c", "0x66"], "0xff") api.answerOnce("eth_getBalance", ["0x70b91ff87a902b53dc6e2f6bda8bb9b330ccd30c", "0x66"], "0xff")
EthereumUpstreamMock upstream = new EthereumUpstreamMock(Chain.ETHEREUM, api) EthereumRpcUpstreamMock upstream = new EthereumRpcUpstreamMock(Chain.ETHEREUM, api)
def upstreams = TestingCommons.multistream(upstream) def upstreams = TestingCommons.multistream(upstream)
def reader = new EthereumReader(upstreams, Caches.default(), calls) def reader = new EthereumReader(upstreams, Caches.default(), calls)
reader.start() reader.start()
@@ -241,7 +241,7 @@ class EthereumReaderSpec extends Specification {
api.answerOnce("eth_getTransactionReceipt", ["0xf85b826fdf98ee0f48f7db001be00472e63ceb056846f4ecac5f0c32878b8ab2"], [ api.answerOnce("eth_getTransactionReceipt", ["0xf85b826fdf98ee0f48f7db001be00472e63ceb056846f4ecac5f0c32878b8ab2"], [
transactionHash: "0xf85b826fdf98ee0f48f7db001be00472e63ceb056846f4ecac5f0c32878b8ab2" transactionHash: "0xf85b826fdf98ee0f48f7db001be00472e63ceb056846f4ecac5f0c32878b8ab2"
]) ])
EthereumUpstreamMock upstream = new EthereumUpstreamMock(Chain.ETHEREUM, api) EthereumRpcUpstreamMock upstream = new EthereumRpcUpstreamMock(Chain.ETHEREUM, api)
def upstreams = TestingCommons.multistream(upstream) def upstreams = TestingCommons.multistream(upstream)
def reader = new EthereumReader(upstreams, Caches.default(), calls) def reader = new EthereumReader(upstreams, Caches.default(), calls)
reader.start() reader.start()
@@ -257,7 +257,7 @@ class EthereumReaderSpec extends Specification {
def "Read receipt from cache if available"() { def "Read receipt from cache if available"() {
setup: setup:
def api = TestingCommons.api() def api = TestingCommons.api()
EthereumUpstreamMock upstream = new EthereumUpstreamMock(Chain.ETHEREUM, api) EthereumRpcUpstreamMock upstream = new EthereumRpcUpstreamMock(Chain.ETHEREUM, api)
def upstreams = TestingCommons.multistream(upstream) def upstreams = TestingCommons.multistream(upstream)
def receiptCache = Mock(ReceiptRedisCache) { def receiptCache = Mock(ReceiptRedisCache) {
1 * it.read(TxId.from("0xf85b826fdf98ee0f48f7db001be00472e63ceb056846f4ecac5f0c32878b8ab2")) >> 1 * it.read(TxId.from("0xf85b826fdf98ee0f48f7db001be00472e63ceb056846f4ecac5f0c32878b8ab2")) >>