diff --git a/demo/test.html b/demo/test.html
new file mode 100644
index 00000000..9a44c15a
--- /dev/null
+++ b/demo/test.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/reference-configuration.adoc b/docs/reference-configuration.adoc
index 0d691617..d71e8589 100644
--- a/docs/reference-configuration.adoc
+++ b/docs/reference-configuration.adoc
@@ -678,7 +678,8 @@ configuration, and may be omitted for most of the situations.
| `role`
| no
-| `standard` (default) or `fallback`.
+| `primary` (default), `secondary` or `fallback`.
+First it makes the requests to the upstreams with role `primary`, then if none are available to upstreams with role `secondary`.
Fallback role mean that the upstream is used only after other upstreams failed or didn't return quorum
| `chain`
diff --git a/src/main/kotlin/io/emeraldpay/dshackle/proxy/WebsocketHandler.kt b/src/main/kotlin/io/emeraldpay/dshackle/proxy/WebsocketHandler.kt
index 51d097cf..e477c47d 100644
--- a/src/main/kotlin/io/emeraldpay/dshackle/proxy/WebsocketHandler.kt
+++ b/src/main/kotlin/io/emeraldpay/dshackle/proxy/WebsocketHandler.kt
@@ -27,7 +27,6 @@ import io.emeraldpay.dshackle.rpc.NativeSubscribe
import io.emeraldpay.etherjar.rpc.json.RequestJson
import io.emeraldpay.etherjar.rpc.json.ResponseJson
import io.netty.buffer.ByteBufInputStream
-import io.netty.buffer.Unpooled
import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory
import reactor.core.publisher.Flux
@@ -74,9 +73,8 @@ class WebsocketHandler(
val eventHandler = accessHandler.start(req, routeConfig.blockchain)
val responses = respond(routeConfig.blockchain, control, requests, eventHandler)
- .map { Unpooled.wrappedBuffer(it.toByteArray()) }
- resp.send(responses)
+ resp.sendString(responses, Charsets.UTF_8)
.then()
}
}
diff --git a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt
index 99aeda3c..31345995 100644
--- a/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt
+++ b/src/main/kotlin/io/emeraldpay/dshackle/rpc/NativeCall.kt
@@ -290,11 +290,7 @@ open class NativeCall(
Mono.just(ctx).flatMap(this::executeOnRemote)
)
.onErrorResume {
- if (it is CallFailure) {
- Mono.just(CallResult.fail(it.id, ctx.nonce, it.reason, ctx))
- } else {
- Mono.just(CallResult.fail(ctx.id, ctx.nonce, it, ctx))
- }
+ Mono.just(CallResult.fail(ctx.id, ctx.nonce, it, ctx))
}
}
@@ -318,21 +314,14 @@ open class NativeCall(
CallResult.ok(ctx.id, ctx.nonce, bytes, it.signature, ctx.upstream.getId(), ctx)
}
.onErrorResume { t ->
- val failure = when (t) {
- is CallFailure -> CallResult.fail(t.id, ctx.nonce, t.reason, ctx)
- is JsonRpcException -> CallResult.fail(ctx.id, ctx.nonce, t.error.code, t.error.message, ctx)
- else -> CallResult.fail(ctx.id, ctx.nonce, t, ctx)
- }
- Mono.just(failure)
+ Mono.just(CallResult.fail(ctx.id, ctx.nonce, t, ctx))
}
.switchIfEmpty(
Mono.fromSupplier {
counter.get().let { attempts ->
CallResult.fail(
- ctx.id,
- ctx.nonce,
- 1,
- errorMessage(attempts, ctx.payload.method),
+ ctx.id, ctx.nonce,
+ CallError(1, "No response or no available upstream for ${ctx.payload.method}", null),
ctx
).also {
countFailure(attempts, ctx)
@@ -498,7 +487,15 @@ open class NativeCall(
is JsonRpcException -> CallError(t.id.asNumber().toInt(), t.error.message, t.error)
is RpcException -> CallError(t.code, t.rpcMessage, null)
is CallFailure -> CallError(t.id, t.reason.message ?: "Upstream Error", null)
- else -> CallError(1, t.message ?: "Upstream Error", null)
+ else -> {
+ // May only happen if it's an unhandled exception.
+ // In this case try to find a meaningless details in the stack. Most important reason for doing that is to find an ID of the request
+ if (t.cause != null) {
+ from(t.cause!!)
+ } else {
+ CallError(1, t.message ?: "Upstream Error", null)
+ }
+ }
}
}
}
@@ -518,8 +515,8 @@ open class NativeCall(
return CallResult(id, nonce, result, null, signature, upstreamId, ctx)
}
- fun fail(id: Int, nonce: Long?, errorCore: Int, errorMessage: String, ctx: ValidCallContext?): CallResult {
- return CallResult(id, nonce, null, CallError(errorCore, errorMessage, null), null, null, ctx)
+ fun fail(id: Int, nonce: Long?, error: CallError, ctx: ValidCallContext?): CallResult {
+ return CallResult(id, nonce, null, error, null, null, ctx)
}
fun fail(id: Int, nonce: Long?, error: Throwable, ctx: ValidCallContext?): CallResult {
diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/DefaultUpstream.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/DefaultUpstream.kt
index 451a53b4..0f967fba 100644
--- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/DefaultUpstream.kt
+++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/DefaultUpstream.kt
@@ -98,6 +98,11 @@ abstract class DefaultUpstream(
}
fun statusByLag(lag: Long, proposed: UpstreamAvailability): UpstreamAvailability {
+ if (options.disableValidation == true) {
+ // if we specifically told that this upstream should be _always valid_ then skip
+ // the status calculation and trust the proposed value as is
+ return proposed
+ }
return if (proposed == UpstreamAvailability.OK) {
when {
lag > 6 -> UpstreamAvailability.SYNCING
diff --git a/src/test/groovy/io/emeraldpay/dshackle/config/CacheConfigReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/config/CacheConfigReaderSpec.groovy
index 555890c6..9f6d962e 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/config/CacheConfigReaderSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/config/CacheConfigReaderSpec.groovy
@@ -23,7 +23,7 @@ class CacheConfigReaderSpec extends Specification {
def "Read full"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("cache-redis-full.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/cache-redis-full.yaml")
when:
def act = reader.read(config)
@@ -39,7 +39,7 @@ class CacheConfigReaderSpec extends Specification {
def "Read disabled"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("cache-redis-disabled.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/cache-redis-disabled.yaml")
when:
def act = reader.read(config)
diff --git a/src/test/groovy/io/emeraldpay/dshackle/config/HealthConfigReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/config/HealthConfigReaderSpec.groovy
index a340c75c..9006581b 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/config/HealthConfigReaderSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/config/HealthConfigReaderSpec.groovy
@@ -24,7 +24,7 @@ class HealthConfigReaderSpec extends Specification {
def "Read empty"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-health-empty.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-health-empty.yaml")
when:
def act = reader.read(config)
@@ -38,7 +38,7 @@ class HealthConfigReaderSpec extends Specification {
def "Read single"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-health-1.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-health-1.yaml")
when:
def act = reader.read(config)
@@ -58,7 +58,7 @@ class HealthConfigReaderSpec extends Specification {
def "Read multiple"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-health-2.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-health-2.yaml")
when:
def act = reader.read(config)
diff --git a/src/test/groovy/io/emeraldpay/dshackle/config/MainConfigReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/config/MainConfigReaderSpec.groovy
index 89d48c42..8a0c0eab 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/config/MainConfigReaderSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/config/MainConfigReaderSpec.groovy
@@ -22,11 +22,12 @@ import spock.lang.Specification
class MainConfigReaderSpec extends Specification {
- MainConfigReader reader = new MainConfigReader(TestingCommons.fileResolver())
-
- def "Read full config"() {
+ def "Read full config with inclusion"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-full.yaml")
+ // the File Resolver should be able to resolve/include files
+ MainConfigReader reader = new MainConfigReader(TestingCommons.fileResolver())
+ // note that it references another config to be included
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-full.yaml")
when:
def act = reader.read(config)
diff --git a/src/test/groovy/io/emeraldpay/dshackle/config/MonitoringConfigReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/config/MonitoringConfigReaderSpec.groovy
index a1fa8f67..eee026ca 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/config/MonitoringConfigReaderSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/config/MonitoringConfigReaderSpec.groovy
@@ -23,7 +23,7 @@ class MonitoringConfigReaderSpec extends Specification {
def "Read basic monitoring config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-monitoring-basic.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-monitoring-basic.yaml")
when:
def act = reader.read(config)
diff --git a/src/test/groovy/io/emeraldpay/dshackle/config/ProxyConfigReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/config/ProxyConfigReaderSpec.groovy
index 8d2f827d..473247df 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/config/ProxyConfigReaderSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/config/ProxyConfigReaderSpec.groovy
@@ -24,7 +24,7 @@ class ProxyConfigReaderSpec extends Specification {
def "Read basic proxy config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-proxy-basic.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-proxy-basic.yaml")
when:
def act = reader.read(config)
@@ -42,7 +42,7 @@ class ProxyConfigReaderSpec extends Specification {
def "Read proxy config with websocket disabled"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-proxy-no-ws.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-proxy-no-ws.yaml")
when:
def act = reader.read(config)
@@ -53,7 +53,7 @@ class ProxyConfigReaderSpec extends Specification {
def "Read proxy config with two elements"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-proxy-two.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-proxy-two.yaml")
when:
def act = reader.read(config)
@@ -73,7 +73,7 @@ class ProxyConfigReaderSpec extends Specification {
def "Read max proxy config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("dshackle-proxy-max.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/dshackle-proxy-max.yaml")
when:
def act = reader.read(config)
diff --git a/src/test/groovy/io/emeraldpay/dshackle/config/UpstreamsConfigReaderSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/config/UpstreamsConfigReaderSpec.groovy
index a58ecbe1..4d198ec0 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/config/UpstreamsConfigReaderSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/config/UpstreamsConfigReaderSpec.groovy
@@ -25,7 +25,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse standard config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-basic.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-basic.yaml")
when:
def act = reader.read(config)
then:
@@ -73,7 +73,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse websocket-only config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-ws-only.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-ws-only.yaml")
when:
def act = reader.read(config)
then:
@@ -98,7 +98,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse full defined websocket config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-ws-full.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-ws-full.yaml")
when:
def act = reader.read(config)
then:
@@ -125,7 +125,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse bitcoin upstreams"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-bitcoin.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-bitcoin.yaml")
when:
def act = reader.read(config)
then:
@@ -173,7 +173,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse bitcoin upstreams with esplora"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-bitcoin-esplora.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-bitcoin-esplora.yaml")
when:
def act = reader.read(config)
then:
@@ -202,7 +202,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse ds config"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-ds.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-ds.yaml")
when:
def act = reader.read(config)
then:
@@ -225,7 +225,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with labels"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-labels.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-labels.yaml")
when:
def act = reader.read(config)
then:
@@ -246,7 +246,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with options"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-options.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-options.yaml")
when:
def act = reader.read(config)
then:
@@ -262,7 +262,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config without defaults"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-no-defaults.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-no-defaults.yaml")
when:
def act = reader.read(config)
then:
@@ -285,7 +285,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with methods"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-methods.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-methods.yaml")
when:
def act = reader.read(config)
then:
@@ -305,7 +305,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with methods and quorum"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-methods-quorum.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-methods-quorum.yaml")
when:
def act = reader.read(config)
then:
@@ -328,7 +328,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with invalid ids"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-no-id.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-no-id.yaml")
when:
def act = reader.read(config)
then:
@@ -355,7 +355,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config without fallback role"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-basic.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-basic.yaml")
when:
def act = reader.read(config)
then:
@@ -367,7 +367,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with fallback role"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-roles.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-roles.yaml")
when:
def act = reader.read(config)
then:
@@ -379,7 +379,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with secondary role"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-roles-2.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-roles-2.yaml")
when:
def act = reader.read(config)
then:
@@ -392,7 +392,7 @@ class UpstreamsConfigReaderSpec extends Specification {
def "Parse config with invalid role"() {
setup:
- def config = this.class.getClassLoader().getResourceAsStream("upstreams-roles-invalid.yaml")
+ def config = this.class.getClassLoader().getResourceAsStream("configs/upstreams-roles-invalid.yaml")
when:
def act = reader.read(config)
then:
diff --git a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy
index 38dd350c..164ee633 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/rpc/NativeCallSpec.groovy
@@ -34,6 +34,8 @@ import io.emeraldpay.dshackle.upstream.Selector
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.calls.ManagedCallMethods
+import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError
+import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
import io.emeraldpay.dshackle.upstream.signature.ResponseSigner
@@ -158,6 +160,35 @@ class NativeCallSpec extends Specification {
.verify(Duration.ofSeconds(1))
}
+ def "Returns error details from remote"() {
+ setup:
+ def quorum = new AlwaysQuorum()
+
+ def nativeCall = nativeCall()
+ nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
+ 1 * create(_, _, _) >> Mock(Reader) {
+ 1 * read(new JsonRpcRequest("eth_test", [], 10)) >> Mono.error(
+ new JsonRpcException(JsonRpcResponse.Id.from(12), new JsonRpcError(-32123, "Foo Bar", "Foo Bar Baz"))
+ )
+ }
+ }
+ def call = new NativeCall.ValidCallContext(12, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
+ new NativeCall.ParsedCallDetails("eth_test", []))
+
+ when:
+ def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))
+ then:
+ resp.isError()
+ with(resp.getError()) {
+ message == "Foo Bar"
+ upstreamError != null
+ with (upstreamError) {
+ code == -32123
+ details == "Foo Bar Baz"
+ }
+ }
+ }
+
def "Packs call exception into response with id"() {
setup:
def nativeCall = nativeCall()
diff --git a/src/test/groovy/io/emeraldpay/dshackle/test/TestingCommons.groovy b/src/test/groovy/io/emeraldpay/dshackle/test/TestingCommons.groovy
index 4f9cd294..b7cd076c 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/test/TestingCommons.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/test/TestingCommons.groovy
@@ -113,7 +113,7 @@ class TestingCommons {
}
static FileResolver fileResolver() {
- return new FileResolver(new File("src/test/resources"))
+ return new FileResolver(new File("src/test/resources/configs"))
}
static BlockContainer blockForEthereum(Long height) {
diff --git a/src/test/groovy/io/emeraldpay/dshackle/upstream/signature/EcdsaSignerSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/upstream/signature/EcdsaSignerSpec.groovy
index 668b5abc..98a8acbb 100644
--- a/src/test/groovy/io/emeraldpay/dshackle/upstream/signature/EcdsaSignerSpec.groovy
+++ b/src/test/groovy/io/emeraldpay/dshackle/upstream/signature/EcdsaSignerSpec.groovy
@@ -49,7 +49,7 @@ class EcdsaSignerSpec extends Specification {
setup:
def conf = new SignatureConfig()
conf.enabled = true
- conf.privateKey = "testing/dshackle/test_key"
+ conf.privateKey = "src/test/resources/signer/test_key"
def signer = new ResponseSignerFactory(conf).getObject() as EcdsaSigner
// To verify the test, check the hash of test key above:
@@ -114,7 +114,7 @@ class EcdsaSignerSpec extends Specification {
def conf = new SignatureConfig()
conf.enabled = true
- conf.privateKey = "testing/dshackle/test_key"
+ conf.privateKey = "src/test/resources/signer/test_key"
def factory = new ResponseSignerFactory(conf)
def sk = factory.readKey(conf.algorithm, conf.privateKey).first
diff --git a/src/test/resources/cache-redis-disabled.yaml b/src/test/resources/configs/cache-redis-disabled.yaml
similarity index 100%
rename from src/test/resources/cache-redis-disabled.yaml
rename to src/test/resources/configs/cache-redis-disabled.yaml
diff --git a/src/test/resources/cache-redis-full.yaml b/src/test/resources/configs/cache-redis-full.yaml
similarity index 100%
rename from src/test/resources/cache-redis-full.yaml
rename to src/test/resources/configs/cache-redis-full.yaml
diff --git a/src/test/resources/dshackle-full.yaml b/src/test/resources/configs/dshackle-full.yaml
similarity index 100%
rename from src/test/resources/dshackle-full.yaml
rename to src/test/resources/configs/dshackle-full.yaml
diff --git a/src/test/resources/dshackle-health-1.yaml b/src/test/resources/configs/dshackle-health-1.yaml
similarity index 100%
rename from src/test/resources/dshackle-health-1.yaml
rename to src/test/resources/configs/dshackle-health-1.yaml
diff --git a/src/test/resources/dshackle-health-2.yaml b/src/test/resources/configs/dshackle-health-2.yaml
similarity index 100%
rename from src/test/resources/dshackle-health-2.yaml
rename to src/test/resources/configs/dshackle-health-2.yaml
diff --git a/src/test/resources/dshackle-health-empty.yaml b/src/test/resources/configs/dshackle-health-empty.yaml
similarity index 100%
rename from src/test/resources/dshackle-health-empty.yaml
rename to src/test/resources/configs/dshackle-health-empty.yaml
diff --git a/src/test/resources/dshackle-monitoring-basic.yaml b/src/test/resources/configs/dshackle-monitoring-basic.yaml
similarity index 100%
rename from src/test/resources/dshackle-monitoring-basic.yaml
rename to src/test/resources/configs/dshackle-monitoring-basic.yaml
diff --git a/src/test/resources/dshackle-proxy-basic.yaml b/src/test/resources/configs/dshackle-proxy-basic.yaml
similarity index 100%
rename from src/test/resources/dshackle-proxy-basic.yaml
rename to src/test/resources/configs/dshackle-proxy-basic.yaml
diff --git a/src/test/resources/dshackle-proxy-max.yaml b/src/test/resources/configs/dshackle-proxy-max.yaml
similarity index 100%
rename from src/test/resources/dshackle-proxy-max.yaml
rename to src/test/resources/configs/dshackle-proxy-max.yaml
diff --git a/src/test/resources/dshackle-proxy-no-ws.yaml b/src/test/resources/configs/dshackle-proxy-no-ws.yaml
similarity index 100%
rename from src/test/resources/dshackle-proxy-no-ws.yaml
rename to src/test/resources/configs/dshackle-proxy-no-ws.yaml
diff --git a/src/test/resources/dshackle-proxy-two.yaml b/src/test/resources/configs/dshackle-proxy-two.yaml
similarity index 100%
rename from src/test/resources/dshackle-proxy-two.yaml
rename to src/test/resources/configs/dshackle-proxy-two.yaml
diff --git a/src/test/resources/upstreams-basic.yaml b/src/test/resources/configs/upstreams-basic.yaml
similarity index 100%
rename from src/test/resources/upstreams-basic.yaml
rename to src/test/resources/configs/upstreams-basic.yaml
diff --git a/src/test/resources/upstreams-bitcoin-esplora.yaml b/src/test/resources/configs/upstreams-bitcoin-esplora.yaml
similarity index 100%
rename from src/test/resources/upstreams-bitcoin-esplora.yaml
rename to src/test/resources/configs/upstreams-bitcoin-esplora.yaml
diff --git a/src/test/resources/upstreams-bitcoin.yaml b/src/test/resources/configs/upstreams-bitcoin.yaml
similarity index 100%
rename from src/test/resources/upstreams-bitcoin.yaml
rename to src/test/resources/configs/upstreams-bitcoin.yaml
diff --git a/src/test/resources/upstreams-ds.yaml b/src/test/resources/configs/upstreams-ds.yaml
similarity index 100%
rename from src/test/resources/upstreams-ds.yaml
rename to src/test/resources/configs/upstreams-ds.yaml
diff --git a/src/test/resources/upstreams-extra.yaml b/src/test/resources/configs/upstreams-extra.yaml
similarity index 100%
rename from src/test/resources/upstreams-extra.yaml
rename to src/test/resources/configs/upstreams-extra.yaml
diff --git a/src/test/resources/upstreams-labels.yaml b/src/test/resources/configs/upstreams-labels.yaml
similarity index 100%
rename from src/test/resources/upstreams-labels.yaml
rename to src/test/resources/configs/upstreams-labels.yaml
diff --git a/src/test/resources/upstreams-methods-quorum.yaml b/src/test/resources/configs/upstreams-methods-quorum.yaml
similarity index 100%
rename from src/test/resources/upstreams-methods-quorum.yaml
rename to src/test/resources/configs/upstreams-methods-quorum.yaml
diff --git a/src/test/resources/upstreams-methods.yaml b/src/test/resources/configs/upstreams-methods.yaml
similarity index 100%
rename from src/test/resources/upstreams-methods.yaml
rename to src/test/resources/configs/upstreams-methods.yaml
diff --git a/src/test/resources/upstreams-no-defaults.yaml b/src/test/resources/configs/upstreams-no-defaults.yaml
similarity index 100%
rename from src/test/resources/upstreams-no-defaults.yaml
rename to src/test/resources/configs/upstreams-no-defaults.yaml
diff --git a/src/test/resources/upstreams-no-id.yaml b/src/test/resources/configs/upstreams-no-id.yaml
similarity index 100%
rename from src/test/resources/upstreams-no-id.yaml
rename to src/test/resources/configs/upstreams-no-id.yaml
diff --git a/src/test/resources/upstreams-options.yaml b/src/test/resources/configs/upstreams-options.yaml
similarity index 100%
rename from src/test/resources/upstreams-options.yaml
rename to src/test/resources/configs/upstreams-options.yaml
diff --git a/src/test/resources/configs/upstreams-priority.yaml b/src/test/resources/configs/upstreams-priority.yaml
new file mode 100644
index 00000000..2a165754
--- /dev/null
+++ b/src/test/resources/configs/upstreams-priority.yaml
@@ -0,0 +1,26 @@
+version: v1
+
+upstreams:
+
+ - id: local
+ chain: ethereum
+ priority: 100
+ connection:
+ ethereum:
+ rpc:
+ url: "http://localhost:8545"
+
+ - id: infura
+ chain: ethereum
+ role: fallback
+ priority: 50
+ connection:
+ ethereum:
+ rpc:
+ url: "https://mainnet.infura.io/v3/fa28c968191849c1aff541ad1d8511f2"
+
+ - id: remote
+ priority: 75
+ connection:
+ grpc:
+ host: "10.2.0.15"
\ No newline at end of file
diff --git a/src/test/resources/upstreams-roles-2.yaml b/src/test/resources/configs/upstreams-roles-2.yaml
similarity index 100%
rename from src/test/resources/upstreams-roles-2.yaml
rename to src/test/resources/configs/upstreams-roles-2.yaml
diff --git a/src/test/resources/upstreams-roles-invalid.yaml b/src/test/resources/configs/upstreams-roles-invalid.yaml
similarity index 100%
rename from src/test/resources/upstreams-roles-invalid.yaml
rename to src/test/resources/configs/upstreams-roles-invalid.yaml
diff --git a/src/test/resources/upstreams-roles.yaml b/src/test/resources/configs/upstreams-roles.yaml
similarity index 100%
rename from src/test/resources/upstreams-roles.yaml
rename to src/test/resources/configs/upstreams-roles.yaml
diff --git a/src/test/resources/upstreams-ws-full.yaml b/src/test/resources/configs/upstreams-ws-full.yaml
similarity index 100%
rename from src/test/resources/upstreams-ws-full.yaml
rename to src/test/resources/configs/upstreams-ws-full.yaml
diff --git a/src/test/resources/upstreams-ws-only.yaml b/src/test/resources/configs/upstreams-ws-only.yaml
similarity index 100%
rename from src/test/resources/upstreams-ws-only.yaml
rename to src/test/resources/configs/upstreams-ws-only.yaml
diff --git a/testing/dshackle/test_key b/src/test/resources/signer/test_key
similarity index 100%
rename from testing/dshackle/test_key
rename to src/test/resources/signer/test_key
diff --git a/testing/dshackle/test_key.pub b/src/test/resources/signer/test_key.pub
similarity index 100%
rename from testing/dshackle/test_key.pub
rename to src/test/resources/signer/test_key.pub
diff --git a/testing/.gitignore b/testing/.gitignore
deleted file mode 100644
index e5a210d4..00000000
--- a/testing/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-gradlew
-gradlew.bat
-gradle/
\ No newline at end of file
diff --git a/testing/README.adoc b/testing/README.adoc
deleted file mode 100644
index 8027d983..00000000
--- a/testing/README.adoc
+++ /dev/null
@@ -1,104 +0,0 @@
-= Dshackle Integration Testing
-
-Test for a correct work using a simulation of different upstream behaviours and checking the Dshackle against it.
-
-.Modules:
-- `dshackle` - Dshackle config used for testing environment
-- `simple-upstream` - upstream simulator with predefines responses
-- `trial` - actual tests
-
-== How to run
-
-NOTE: Run commands in project's root dir
-
-NOTE: You need to open multiple consoles, since each command runs on foreground
-
-== Basic Test
-
-Makes some basic checks with a mocked upstreams
-
-=== Run upstream emulator
-
-.Runs two instances of RPC server
-[source,bash]
-----
-DSHACKLE_TESTUP_PORT=18545 ./gradlew -p testing/simple-upstream run
-DSHACKLE_TESTUP_PORT=18546 ./gradlew -p testing/simple-upstream run
-----
-
-=== Run Dshackle
-
-[source,bash]
-----
-./gradlew run --args="--configPath=./testing/dshackle/dshackle-basic.yaml"
-----
-
-=== Run tests
-
-[source,bash]
-----
-./testing/trial/gradlew -p testing/trial -PdshackleTrialMode=basic cleanTest test
-----
-
-== Real (Mainnet) Test
-
-=== Run Dshackle
-
-First you have to provide configuration to an upstream connected to the mainnet.
-It may be a local Geth instance, or an other provider, like Infura (note that the test config doesn't support TLS or other auth)
-
-[source,bash]
-----
-export DSHACKLE_TEST_ETH1_RPC=
-export DSHACKLE_TEST_ETH1_WS=
-export DSHACKLE_TEST_ETH1_WSORIGIN=
-----
-
-For a local Geth it would be:
-
-[source,bash]
-----
-export DSHACKLE_TEST_ETH1_RPC=http://127.0.0.1:8545
-export DSHACKLE_TEST_ETH1_WS=ws://127.0.0.1:8546
-export DSHACKLE_TEST_ETH1_WSORIGIN=http://127.0.0.1:8546
-----
-
-Finally, run the Dshackle instance:
-
-[source,bash]
-----
-./gradlew run --args="--configPath=./testing/dshackle/dshackle-real.yaml"
-----
-
-=== Run tests
-
-[source,bash]
-----
-./testing/trial/gradlew -p testing/trial -PdshackleTrialMode=real cleanTest test
-----
-
-== Real (Rinkeby) Test
-
-Runs requests against a Rinkeby Testnet.
-Configuration is similar to the Mainnet config, but instead of `ETH1` is has `RINKEBY`.
-
-[source,bash]
-----
-export DSHACKLE_TEST_RINKEBY_RPC=
-export DSHACKLE_TEST_RINKEBY_WS=
-export DSHACKLE_TEST_RINKEBY_WSORIGIN=
-----
-
-And run the Dshackle instance:
-
-[source,bash]
-----
-./gradlew run --args="--configPath=./testing/dshackle/dshackle-rinkeby.yaml"
-----
-
-=== Run tests
-
-[source,bash]
-----
-./testing/trial/gradlew -p testing/trial -PdshackleTrialMode=rinkeby cleanTest test
-----
diff --git a/testing/dshackle/README.adoc b/testing/dshackle/README.adoc
deleted file mode 100644
index 46dc3bc3..00000000
--- a/testing/dshackle/README.adoc
+++ /dev/null
@@ -1,14 +0,0 @@
-= Testing Server
-
-.Run from project root directory:
-[source,bash]
-----
-./gradlew run --args="--configPath=./testing/dshackle/dshackle-mock.yaml"
-----
-
-or
-
-[source,bash]
-----
-./gradlew run --args="--configPath=./testing/dshackle/dshackle-real.yaml"
-----
diff --git a/testing/dshackle/dshackle-basic.yaml b/testing/dshackle/dshackle-basic.yaml
deleted file mode 100644
index 56515c78..00000000
--- a/testing/dshackle/dshackle-basic.yaml
+++ /dev/null
@@ -1,50 +0,0 @@
-version: v1
-port: 12448
-
-tls:
- enabled: false
-
-cluster:
- upstreams:
- - id: test-1
- node-id: 1
- chain: ethereum
- methods:
- enabled:
- - name: debug_traceTransaction
- - name: test_foo
- options:
- disable-validation: true
- connection:
- ethereum-pos:
- execution:
- rpc:
- url: "http://localhost:18545"
-
- - id: test-2
- node-id: 2
- chain: ethereum
- options:
- disable-validation: true
- connection:
- execution:
- ethereum-pos:
- rpc:
- url: "http://localhost:18546"
-
-cache:
- redis:
- enabled: false
-
-signed-response:
- enabled: true
- algorithm: SECP256K1
- private-key: "./test_key"
-
-proxy:
- port: 18080
- tls:
- enabled: false
- routes:
- - id: eth
- blockchain: ethereum
\ No newline at end of file
diff --git a/testing/dshackle/dshackle-real.yaml b/testing/dshackle/dshackle-real.yaml
deleted file mode 100644
index a8e289f0..00000000
--- a/testing/dshackle/dshackle-real.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-version: v1
-port: 12448
-
-tls:
- enabled: false
-
-cluster:
- upstreams:
- - id: eth-1
- chain: ethereum
- connection:
- ethereum:
- rpc:
- url: "${DSHACKLE_TEST_ETH1_RPC}"
- ws:
- url: "${DSHACKLE_TEST_ETH1_WS}"
- origin: "${DSHACKLE_TEST_ETH1_WSORIGIN}"
-
-cache:
- redis:
- enabled: false
-
-proxy:
- port: 18081
- preserve-batch-order: true
- tls:
- enabled: false
- routes:
- - id: eth
- blockchain: ethereum
\ No newline at end of file
diff --git a/testing/dshackle/dshackle-rinkeby.yaml b/testing/dshackle/dshackle-rinkeby.yaml
deleted file mode 100644
index e0e1d3a8..00000000
--- a/testing/dshackle/dshackle-rinkeby.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-version: v1
-port: 12448
-
-tls:
- enabled: false
-
-cluster:
- upstreams:
- - id: rinkeby-1
- chain: rinkeby
- connection:
- ethereum:
- rpc:
- url: "${DSHACKLE_TEST_RINKEBY_RPC}"
-
-cache:
- redis:
- enabled: false
-
-proxy:
- port: 18081
- tls:
- enabled: false
- routes:
- - id: rinkeby
- blockchain: rinkeby
\ No newline at end of file
diff --git a/testing/simple-upstream/README.adoc b/testing/simple-upstream/README.adoc
deleted file mode 100644
index caab006c..00000000
--- a/testing/simple-upstream/README.adoc
+++ /dev/null
@@ -1,6 +0,0 @@
-= Simple Testing Upstream
-
-.Run from current directory
-----
-./gradlew run
-----
\ No newline at end of file
diff --git a/testing/simple-upstream/build.gradle b/testing/simple-upstream/build.gradle
deleted file mode 100644
index 72b72e50..00000000
--- a/testing/simple-upstream/build.gradle
+++ /dev/null
@@ -1,22 +0,0 @@
-plugins {
- id 'java'
- id 'groovy'
- id 'idea'
- id 'application'
-}
-
-repositories {
- mavenLocal()
- mavenCentral()
-}
-
-dependencies {
- implementation "com.sparkjava:spark-core:2.9.1"
- implementation "org.codehaus.groovy:groovy:3.0.4"
- implementation "com.fasterxml.jackson.core:jackson-core:2.9.8"
- implementation "com.fasterxml.jackson.core:jackson-databind:2.9.8"
-}
-
-application {
- mainClassName = 'testing.SimpleUpstream'
-}
\ No newline at end of file
diff --git a/testing/simple-upstream/settings.gradle b/testing/simple-upstream/settings.gradle
deleted file mode 100644
index faa039c6..00000000
--- a/testing/simple-upstream/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-rootProject.name = 'dshackle-testing-simple-upstream'
\ No newline at end of file
diff --git a/testing/simple-upstream/src/main/groovy/testing/BlocksHandler.groovy b/testing/simple-upstream/src/main/groovy/testing/BlocksHandler.groovy
deleted file mode 100644
index 11526f97..00000000
--- a/testing/simple-upstream/src/main/groovy/testing/BlocksHandler.groovy
+++ /dev/null
@@ -1,32 +0,0 @@
-package testing
-
-import com.fasterxml.jackson.databind.ObjectMapper
-
-class BlocksHandler implements CallHandler {
-
- ObjectMapper objectMapper
- ResourceResponse resourceResponse
-
- BlocksHandler(ObjectMapper objectMapper) {
- this.objectMapper = objectMapper
- this.resourceResponse = new ResourceResponse(objectMapper)
- }
-
- @Override
- Result handle(String method, List