Merge branch 'master' into network_specific_methods_support

# Conflicts:
#	src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt
This commit is contained in:
Maksim Fomenkov
2022-11-28 18:38:48 +04:00
152 changed files with 775 additions and 1214 deletions

View File

@@ -21,7 +21,7 @@ import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.test.IntegrationTestingCommons
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.cache
import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.test.IntegrationTestingCommons
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.lettuce.core.api.StatefulRedisConnection
import spock.lang.IgnoreIf
import spock.lang.Specification

View File

@@ -6,7 +6,7 @@ import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.data.DefaultContainer
import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.test.IntegrationTestingCommons
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId
import io.emeraldpay.etherjar.rpc.json.TransactionReceiptJson

View File

@@ -23,7 +23,7 @@ import io.emeraldpay.dshackle.data.TxContainer
import io.emeraldpay.dshackle.data.TxId
import io.emeraldpay.dshackle.test.IntegrationTestingCommons
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId
import io.emeraldpay.etherjar.domain.Wei

View File

@@ -15,7 +15,7 @@
*/
package io.emeraldpay.dshackle.config
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class HealthConfigReaderSpec extends Specification {

View File

@@ -17,7 +17,7 @@ package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class MainConfigReaderSpec extends Specification {

View File

@@ -15,7 +15,7 @@
*/
package io.emeraldpay.dshackle.config
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class ProxyConfigReaderSpec extends Specification {

View File

@@ -15,7 +15,7 @@
*/
package io.emeraldpay.dshackle.config
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class TokensConfigReaderSpec extends Specification {

View File

@@ -20,7 +20,7 @@ import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class HealthCheckSetupSpec extends Specification {

View File

@@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import io.emeraldpay.dshackle.Global
import io.emeraldpay.dshackle.config.AccessLogConfig
import io.emeraldpay.dshackle.config.MainConfig
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
import java.time.Instant

View File

@@ -16,7 +16,7 @@
package io.emeraldpay.dshackle.monitoring.accesslog
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.grpc.Attributes
import io.grpc.Grpc
import io.grpc.Metadata

View File

@@ -2,7 +2,7 @@ package io.emeraldpay.dshackle.monitoring.accesslog
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class EventsBuilderSubscribeBalanceSpec extends Specification {

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.proxy
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import org.jetbrains.annotations.NotNull
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

View File

@@ -23,7 +23,7 @@ import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.step.StepCounter
import reactor.core.publisher.Flux

View File

@@ -6,7 +6,7 @@ import io.emeraldpay.dshackle.config.ProxyConfig
import io.emeraldpay.dshackle.monitoring.accesslog.AccessHandlerHttp
import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.dshackle.rpc.NativeSubscribe
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.netty.http.server.HttpServerRoutes
import spock.lang.Specification

View File

@@ -20,7 +20,7 @@ import io.emeraldpay.dshackle.rpc.NativeCall
import io.emeraldpay.dshackle.rpc.NativeSubscribe
import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.etherjar.rpc.json.RequestJson
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.micrometer.core.instrument.Counter
import reactor.core.publisher.Flux
import reactor.core.publisher.Sinks

View File

@@ -25,7 +25,7 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.rpc.RpcResponseError
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.rpc.RpcException
import reactor.core.publisher.Mono
import reactor.test.StepVerifier

View File

@@ -37,7 +37,7 @@ import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.upstream.signature.ResponseSigner
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.rpc.RpcException
import io.emeraldpay.etherjar.rpc.RpcResponseError
import reactor.core.publisher.Flux
@@ -246,9 +246,7 @@ class NativeCallSpec extends Specification {
def "Returns error for unsupported chain"() {
setup:
def upstreams = Mock(MultistreamHolder) {
_ * it.observeChains() >> Flux.empty()
}
def upstreams = Mock(MultistreamHolder)
def nativeCall = nativeCall(upstreams)
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
@@ -454,7 +452,7 @@ class NativeCallSpec extends Specification {
.collectList().block(Duration.ofSeconds(1)).first()
then:
act instanceof NativeCall.ValidCallContext
act.requestDecorator instanceof NativeCall.GetFilterUpdatesDecorator
act.requestDecorator instanceof NativeCall.WithFilterIdDecorator
}
def "Prepare call adds decorator for eth_uninstallFilter"() {
@@ -485,7 +483,7 @@ class NativeCallSpec extends Specification {
.collectList().block(Duration.ofSeconds(1)).first()
then:
act instanceof NativeCall.ValidCallContext
act.requestDecorator instanceof NativeCall.GetFilterUpdatesDecorator
act.requestDecorator instanceof NativeCall.WithFilterIdDecorator
}
def "Parse empty params"() {
@@ -545,7 +543,7 @@ class NativeCallSpec extends Specification {
def nativeCall = nativeCall()
def ctx = new NativeCall.ValidCallContext(1, null, Stub(Multistream), Selector.empty, new AlwaysQuorum(),
new NativeCall.RawCallDetails("eth_getFilterUpdates", '["0xabcd"]'),
new NativeCall.GetFilterUpdatesDecorator(), new NativeCall.NoneResultDecorator())
new NativeCall.WithFilterIdDecorator(), new NativeCall.NoneResultDecorator())
when:
def act = nativeCall.parseParams(ctx)
then:
@@ -566,7 +564,7 @@ class NativeCallSpec extends Specification {
}
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
new NativeCall.ParsedCallDetails("eth_getFilterChanges", []),
new NativeCall.GetFilterUpdatesDecorator(), new NativeCall.CreateFilterDecorator())
new NativeCall.WithFilterIdDecorator(), new NativeCall.CreateFilterDecorator())
when:
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))
@@ -588,7 +586,7 @@ class NativeCallSpec extends Specification {
}
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
new NativeCall.ParsedCallDetails("eth_getFilterChanges", []),
new NativeCall.GetFilterUpdatesDecorator(), new NativeCall.CreateFilterDecorator())
new NativeCall.WithFilterIdDecorator(), new NativeCall.CreateFilterDecorator())
when:
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))

View File

@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumSubscribe
import io.emeraldpay.dshackle.upstream.signature.NoSigner
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.core.publisher.Flux
import reactor.test.StepVerifier
import spock.lang.Specification

View File

@@ -26,7 +26,7 @@ import io.emeraldpay.dshackle.test.EthereumPosRpcUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.test.MultistreamHolderMock
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosRpcUpstream
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson

View File

@@ -6,7 +6,7 @@ import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.core.publisher.Mono
import reactor.test.StepVerifier
import spock.lang.Specification

View File

@@ -30,7 +30,7 @@ import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinReader
import io.emeraldpay.dshackle.upstream.bitcoin.XpubAddresses
import io.emeraldpay.dshackle.upstream.bitcoin.data.SimpleUnspent
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import org.bitcoinj.core.Address
import org.bitcoinj.params.MainNetParams
import org.bitcoinj.params.TestNet3Params

View File

@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinReader
import io.emeraldpay.dshackle.upstream.bitcoin.CachingMempoolData
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.test.StepVerifier

View File

@@ -14,7 +14,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.subscribe.json.LogMessage
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId
import io.emeraldpay.etherjar.hex.Hex32
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.erc20.ERC20Token
import io.emeraldpay.etherjar.hex.HexData

View File

@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.test.MultistreamHolderMock
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson
import reactor.test.StepVerifier

View File

@@ -28,7 +28,7 @@ import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId
import io.emeraldpay.etherjar.rpc.json.BlockJson

View File

@@ -4,21 +4,24 @@ import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.cache.CachesFactory
import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.quorum.NonEmptyQuorum
import io.emeraldpay.dshackle.upstream.CallTargetsHolder
import io.emeraldpay.dshackle.upstream.CurrentMultistreamHolder
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import org.springframework.context.ApplicationEventPublisher
import spock.lang.Specification
class ConfiguredUpstreamsSpec extends Specification {
def "Applied quorum to extra methods"() {
setup:
def currentUpstreams = Mock(CurrentMultistreamHolder) {
_ * getDefaultMethods(Chain.ETHEREUM) >> new DefaultEthereumMethods(Chain.ETHEREUM)
}
def callTargetsHolder = new CallTargetsHolder()
def configurer = new ConfiguredUpstreams(
currentUpstreams, Stub(FileResolver), Stub(UpstreamsConfig)
Stub(FileResolver),
Stub(UpstreamsConfig),
callTargetsHolder,
Mock(ApplicationEventPublisher)
)
def methods = new UpstreamsConfig.Methods(
[
@@ -38,11 +41,12 @@ class ConfiguredUpstreamsSpec extends Specification {
def "Got static response from extra methods"() {
setup:
def currentUpstreams = Mock(CurrentMultistreamHolder) {
_ * getDefaultMethods(Chain.ETHEREUM) >> new DefaultEthereumMethods(Chain.ETHEREUM)
}
def callTargetsHolder = new CallTargetsHolder()
def configurer = new ConfiguredUpstreams(
currentUpstreams, Stub(FileResolver), Stub(UpstreamsConfig)
Stub(FileResolver),
Stub(UpstreamsConfig),
callTargetsHolder,
Mock(ApplicationEventPublisher)
)
def methods = new UpstreamsConfig.Methods(
[
@@ -61,7 +65,12 @@ class ConfiguredUpstreamsSpec extends Specification {
def "Calculate node-id"() {
setup:
def configurer = new ConfiguredUpstreams(Stub(CurrentMultistreamHolder), Stub(FileResolver), Stub(UpstreamsConfig)
def callTargetsHolder = new CallTargetsHolder()
def configurer = new ConfiguredUpstreams(
Stub(FileResolver),
Stub(UpstreamsConfig),
callTargetsHolder,
Mock(ApplicationEventPublisher)
)
expect:
configurer.getHash(node, src) == expected
@@ -75,7 +84,12 @@ class ConfiguredUpstreamsSpec extends Specification {
def "Calculate node-id conflicting results"() {
setup:
def configurer = new ConfiguredUpstreams(Stub(CurrentMultistreamHolder), Stub(FileResolver), Stub(UpstreamsConfig)
def callTargetsHolder = new CallTargetsHolder()
def configurer = new ConfiguredUpstreams(
Stub(FileResolver),
Stub(UpstreamsConfig),
callTargetsHolder,
Mock(ApplicationEventPublisher)
)
when:
def h1 = configurer.getHash(null, "hohoho")

View File

@@ -8,7 +8,7 @@ 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 io.emeraldpay.dshackle.Chain
class ConnectorFactoryMock implements ConnectorFactory {
Reader<JsonRpcRequest, JsonRpcResponse> api

View File

@@ -31,7 +31,7 @@ import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import org.jetbrains.annotations.NotNull
import org.reactivestreams.Publisher

View File

@@ -30,7 +30,7 @@ import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import org.jetbrains.annotations.NotNull
import org.reactivestreams.Publisher

View File

@@ -30,10 +30,9 @@ import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosRpcUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.Chain
import org.jetbrains.annotations.NotNull
import reactor.core.publisher.Flux
class MultistreamHolderMock implements MultistreamHolder {
@@ -81,20 +80,6 @@ class MultistreamHolderMock implements MultistreamHolder {
return upstreams.keySet().toList()
}
@Override
Flux<Chain> observeChains() {
return Flux.fromIterable(getAvailable())
}
@Override
DefaultEthereumMethods getDefaultMethods(@NotNull Chain chain) {
if (target[chain] == null) {
DefaultEthereumMethods targets = new DefaultEthereumMethods(chain)
target[chain] = targets
}
return target[chain]
}
@Override
boolean isAvailable(@NotNull Chain chain) {
return upstreams.containsKey(chain)

View File

@@ -24,14 +24,16 @@ import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.BlockId
import io.emeraldpay.dshackle.reader.EmptyReader
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.dshackle.upstream.CallTargetsHolder
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumPosMultiStream
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.micrometer.core.instrument.MeterRegistry
import io.micrometer.core.instrument.logging.LoggingMeterRegistry
import org.apache.commons.lang3.StringUtils
@@ -90,6 +92,21 @@ class TestingCommons {
return new CachesFactory(new CacheConfig())
}
static List<Multistream> defaultMultistreams() {
return [
multistreamWithoutUpstreams(Chain.ETHEREUM),
multistreamClassicWithoutUpstreams(Chain.ETHEREUM_CLASSIC)
]
}
static Multistream multistreamWithoutUpstreams(Chain chain) {
return new EthereumPosMultiStream(chain, [], emptyCaches().getCaches(chain))
}
static Multistream multistreamClassicWithoutUpstreams(Chain chain) {
return new EthereumMultistream(chain, [], emptyCaches().getCaches(chain))
}
static FileResolver fileResolver() {
return new FileResolver(new File("src/test/resources"))
}
@@ -126,4 +143,6 @@ class TestingCommons {
}
static MeterRegistry meterRegistry = new LoggingMeterRegistry()
static CallTargetsHolder callTargetsHolder = new CallTargetsHolder()
}

View File

@@ -15,21 +15,21 @@
*/
package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.startup.UpstreamChange
import io.emeraldpay.dshackle.startup.UpstreamChangeEvent
import io.emeraldpay.dshackle.test.EthereumPosRpcUpstreamMock
import io.emeraldpay.dshackle.test.EthereumRpcUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class CurrentMultistreamHolderSpec extends Specification {
def "add upstream"() {
setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def current = new CurrentMultistreamHolder(TestingCommons.defaultMultistreams())
def up = new EthereumPosRpcUpstreamMock("test", Chain.ETHEREUM, TestingCommons.api())
when:
current.update(new UpstreamChange(Chain.ETHEREUM, up, UpstreamChange.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up, UpstreamChangeEvent.ChangeType.ADDED))
then:
current.getAvailable() == [Chain.ETHEREUM]
current.getUpstream(Chain.ETHEREUM).getAll()[0] == up
@@ -37,14 +37,15 @@ class CurrentMultistreamHolderSpec extends Specification {
def "add multiple upstreams"() {
setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def current = new CurrentMultistreamHolder(TestingCommons.defaultMultistreams())
def up1 = new EthereumPosRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
def up2 = new EthereumRpcUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
def up3 = new EthereumPosRpcUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
when:
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, up3, UpstreamChange.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up1, UpstreamChangeEvent.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM_CLASSIC).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM_CLASSIC, up2, UpstreamChangeEvent.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up3, UpstreamChangeEvent.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM_CLASSIC).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up3, UpstreamChangeEvent.ChangeType.ADDED))
then:
current.getAvailable().toSet() == [Chain.ETHEREUM, Chain.ETHEREUM_CLASSIC].toSet()
current.getUpstream(Chain.ETHEREUM).getAll().toSet() == [up1, up3].toSet()
@@ -53,16 +54,16 @@ class CurrentMultistreamHolderSpec extends Specification {
def "remove upstream"() {
setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def current = new CurrentMultistreamHolder(TestingCommons.defaultMultistreams())
def up1 = new EthereumPosRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
def up2 = new EthereumRpcUpstreamMock("test2", Chain.ETHEREUM_CLASSIC, TestingCommons.api())
def up3 = new EthereumPosRpcUpstreamMock("test3", Chain.ETHEREUM, TestingCommons.api())
def up1_del = new EthereumPosRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
when:
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, up3, UpstreamChange.ChangeType.ADDED))
current.update(new UpstreamChange(Chain.ETHEREUM, up1_del, UpstreamChange.ChangeType.REMOVED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up1, UpstreamChangeEvent.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM_CLASSIC).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM_CLASSIC, up2, UpstreamChangeEvent.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up3, UpstreamChangeEvent.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up1_del, UpstreamChangeEvent.ChangeType.REMOVED))
then:
current.getAvailable().toSet() == [Chain.ETHEREUM, Chain.ETHEREUM_CLASSIC].toSet()
current.getUpstream(Chain.ETHEREUM).getAll().toSet() == [up3].toSet()
@@ -71,7 +72,7 @@ class CurrentMultistreamHolderSpec extends Specification {
def "available after adding"() {
setup:
def current = new CurrentMultistreamHolder(TestingCommons.emptyCaches())
def current = new CurrentMultistreamHolder(TestingCommons.defaultMultistreams())
def up1 = new EthereumPosRpcUpstreamMock("test1", Chain.ETHEREUM, TestingCommons.api())
when:
@@ -80,7 +81,7 @@ class CurrentMultistreamHolderSpec extends Specification {
!act
when:
current.update(new UpstreamChange(Chain.ETHEREUM, up1, UpstreamChange.ChangeType.ADDED))
current.getUpstream(Chain.ETHEREUM).onUpstreamChange(new UpstreamChangeEvent(Chain.ETHEREUM, up1, UpstreamChangeEvent.ChangeType.ADDED))
act = current.isAvailable(Chain.ETHEREUM)
then:

View File

@@ -24,7 +24,7 @@ import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.ethereum.EthereumRpcUpstream
import io.emeraldpay.dshackle.upstream.ethereum.connectors.EthereumConnectorFactory
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.test.StepVerifier
import spock.lang.Retry
import spock.lang.Specification

View File

@@ -16,7 +16,7 @@
package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import org.springframework.context.Lifecycle
import io.emeraldpay.dshackle.upstream.Lifecycle
import reactor.core.publisher.Flux
import spock.lang.Specification

View File

@@ -33,7 +33,7 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import org.jetbrains.annotations.NotNull
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

View File

@@ -1,6 +1,6 @@
package io.emeraldpay.dshackle.upstream.calls
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class DefaultEthereumMethodsSpec extends Specification {

View File

@@ -23,7 +23,7 @@ import io.emeraldpay.dshackle.quorum.NonceQuorum
import io.emeraldpay.dshackle.quorum.NotLaggingQuorum
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
class ManagedCallMethodsSpec extends Specification {

View File

@@ -27,7 +27,7 @@ import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.erc20.ERC20Token
import io.emeraldpay.etherjar.hex.HexData
import io.emeraldpay.etherjar.rpc.json.TransactionCallJson
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import spock.lang.Specification
import java.time.Duration

View File

@@ -11,7 +11,7 @@ import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId

View File

@@ -29,7 +29,7 @@ import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.Multistream
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.domain.Address
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.domain.TransactionId

View File

@@ -9,7 +9,7 @@ import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.reader.Reader
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.emeraldpay.etherjar.rpc.json.BlockJson
import org.apache.commons.collections4.functors.ConstantFactory
import reactor.core.publisher.Mono

View File

@@ -4,7 +4,7 @@ import io.emeraldpay.dshackle.test.MockWSServer
import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.test.StepVerifier
import spock.lang.Shared
import spock.lang.Specification

View File

@@ -25,7 +25,7 @@ import io.emeraldpay.etherjar.rpc.RpcResponseError
import io.emeraldpay.etherjar.rpc.json.BlockJson
import io.emeraldpay.etherjar.rpc.json.TransactionJson
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import reactor.core.publisher.Flux
import reactor.test.StepVerifier
import spock.lang.Specification

View File

@@ -29,7 +29,7 @@ import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcGrpcClient
import io.emeraldpay.dshackle.upstream.rpcclient.RpcMetrics
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.grpc.stub.StreamObserver
import io.emeraldpay.etherjar.domain.BlockHash
import io.emeraldpay.etherjar.rpc.json.BlockJson

View File

@@ -22,7 +22,7 @@ import io.emeraldpay.dshackle.test.MockGrpcServer
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.DefaultUpstream
import io.emeraldpay.dshackle.upstream.forkchoice.MostWorkForkChoice
import io.emeraldpay.grpc.Chain
import io.emeraldpay.dshackle.Chain
import io.grpc.stub.StreamObserver
import reactor.test.StepVerifier
import spock.lang.Specification

View File

@@ -0,0 +1,111 @@
package io.emeraldpay.dshackle
import io.emeraldpay.api.proto.BlockchainGrpc
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common.ChainRef
import io.emeraldpay.dshackle.config.MainConfig
import io.emeraldpay.dshackle.config.MainConfigReader
import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.github.ganchix.ganache.Account
import io.github.ganchix.ganache.GanacheContainer
import io.grpc.BindableService
import io.grpc.inprocess.InProcessChannelBuilder
import io.grpc.inprocess.InProcessServerBuilder
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Import
import org.springframework.context.annotation.Profile
import org.springframework.test.context.ActiveProfiles
import org.springframework.util.ResourceUtils
import java.math.BigInteger
import java.net.URI
@SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])
@Import(Config::class)
@ActiveProfiles("integration-test")
class IntegrationTest {
@Autowired
lateinit var services: List<BindableService>
lateinit var stub: BlockchainGrpc.BlockchainBlockingStub
companion object {
val PRIVATE_KEY_0 = "ae020c8ddb6fbc24e167b011666639d2ce3d4aa0d9c13d02d726d6865618a781"
val PRIVATE_KEY_1 = "81ad1ba5c4da47feb0f0163c0c61a66c4d0e6a66bd839827444b1e3362016140"
var ganacheContainer: GanacheContainer<*> = GanacheContainer<Nothing>().apply {
withAccounts(
listOf(
Account.builder().privateKey(PRIVATE_KEY_0).balance(BigInteger.valueOf(2000000000000000000)).build(),
Account.builder().privateKey(PRIVATE_KEY_1).balance(BigInteger.valueOf(2000000000000000000)).build()
)
)
}
init {
ganacheContainer.start()
}
}
@BeforeEach
fun prepare() {
val serverName = InProcessServerBuilder.generateName()
val builder = InProcessServerBuilder.forName(serverName)
.directExecutor()
services.forEach { builder.addService(it) }
val managedChannel = InProcessChannelBuilder.forName(serverName).directExecutor().build()
val server = builder.build()
server.start()
stub = BlockchainGrpc.newBlockingStub(managedChannel)
}
@Test
fun test() {
val result = stub.describe(BlockchainOuterClass.DescribeRequest.newBuilder().build())
Assertions.assertThat(result.chainsCount).isEqualTo(1)
Assertions.assertThat(result.chainsList[0].chain).isEqualTo(ChainRef.CHAIN_ETHEREUM)
Assertions.assertThat(result.chainsList[0].nodesCount).isEqualTo(1)
}
@TestConfiguration
open class Config {
@Bean
@Profile("integration-test")
open fun mainConfig(@Autowired fileResolver: FileResolver): MainConfig {
val reader = MainConfigReader(fileResolver)
val config = reader.read(
ResourceUtils.getFile("classpath:integration/dshackle.yaml")
.inputStream()
)!!
patch(config)
return config
}
private fun patch(config: MainConfig) {
config.upstreams?.upstreams?.add(
UpstreamsConfig.Upstream<UpstreamsConfig.EthereumPosConnection>().apply {
id = "ganache"
nodeId = 1
chain = "ethereum"
connection = UpstreamsConfig.EthereumPosConnection().apply {
execution = UpstreamsConfig.EthereumConnection().apply {
rpc = UpstreamsConfig.HttpEndpoint(
URI.create(
"http://" + ganacheContainer.getHost() + ":" + ganacheContainer.getMappedPort(8545) + "/"
)
)
}
}
}
)
}
}
}

View File

@@ -0,0 +1,21 @@
version: v1
host: 0.0.0.0
port: 2450
tls:
enabled: false
proxy:
host: 0.0.0.0
port: 8550
routes:
- id: eth
blockchain: ethereum
monitoring:
enabled: false
extended: true
signed-response:
enabled: false
cluster:
upstreams: