Merge pull request #120 from p2p-org/provided-upstream-id
propagate grpc provided upstream id
This commit is contained in:
@@ -29,6 +29,7 @@ open class AlwaysQuorum : CallQuorum {
|
|||||||
private var result: ByteArray? = null
|
private var result: ByteArray? = null
|
||||||
private var rpcError: JsonRpcError? = null
|
private var rpcError: JsonRpcError? = null
|
||||||
private var sig: ResponseSigner.Signature? = null
|
private var sig: ResponseSigner.Signature? = null
|
||||||
|
private var providedUpstreamId: String? = null
|
||||||
private val resolvers: MutableCollection<Upstream> = ConcurrentLinkedQueue()
|
private val resolvers: MutableCollection<Upstream> = ConcurrentLinkedQueue()
|
||||||
|
|
||||||
override fun init(head: Head) {
|
override fun init(head: Head) {
|
||||||
@@ -46,15 +47,29 @@ open class AlwaysQuorum : CallQuorum {
|
|||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun record(response: ByteArray, signature: ResponseSigner.Signature?, upstream: Upstream): Boolean {
|
override fun getProvidedUpstreamId(): String? {
|
||||||
|
return providedUpstreamId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun record(
|
||||||
|
response: ByteArray,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
): Boolean {
|
||||||
result = response
|
result = response
|
||||||
resolved = true
|
resolved = true
|
||||||
sig = signature
|
sig = signature
|
||||||
resolvers.add(upstream)
|
resolvers.add(upstream)
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun record(error: JsonRpcException, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun record(
|
||||||
|
error: JsonRpcException,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream
|
||||||
|
) {
|
||||||
this.rpcError = error.error
|
this.rpcError = error.error
|
||||||
sig = signature
|
sig = signature
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ open class BroadcastQuorum(
|
|||||||
private var txid: String? = null
|
private var txid: String? = null
|
||||||
private var calls = 0
|
private var calls = 0
|
||||||
private var sig: ResponseSigner.Signature? = null
|
private var sig: ResponseSigner.Signature? = null
|
||||||
|
private var providedUpstreamId: String? = null
|
||||||
|
|
||||||
override fun init(head: Head) {
|
override fun init(head: Head) {
|
||||||
}
|
}
|
||||||
@@ -48,21 +49,39 @@ open class BroadcastQuorum(
|
|||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordValue(response: ByteArray, responseValue: String?, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun getProvidedUpstreamId(): String? {
|
||||||
|
return providedUpstreamId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recordValue(
|
||||||
|
response: ByteArray,
|
||||||
|
responseValue: String?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
) {
|
||||||
calls++
|
calls++
|
||||||
if (txid == null && responseValue != null) {
|
if (txid == null && responseValue != null) {
|
||||||
txid = responseValue
|
txid = responseValue
|
||||||
sig = signature
|
sig = signature
|
||||||
result = response
|
result = response
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordError(response: ByteArray?, errorMessage: String?, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun recordError(
|
||||||
|
response: ByteArray?,
|
||||||
|
errorMessage: String?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
) {
|
||||||
// can be "message: known transaction: TXID", "Transaction with the same hash was already imported" or "message: Nonce too low"
|
// can be "message: known transaction: TXID", "Transaction with the same hash was already imported" or "message: Nonce too low"
|
||||||
calls++
|
calls++
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = response
|
result = response
|
||||||
sig = signature
|
sig = signature
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,20 @@ interface CallQuorum {
|
|||||||
fun isResolved(): Boolean
|
fun isResolved(): Boolean
|
||||||
fun isFailed(): Boolean
|
fun isFailed(): Boolean
|
||||||
|
|
||||||
fun record(response: ByteArray, signature: ResponseSigner.Signature?, upstream: Upstream): Boolean
|
fun record(
|
||||||
fun record(error: JsonRpcException, signature: ResponseSigner.Signature?, upstream: Upstream)
|
response: ByteArray,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
): Boolean
|
||||||
|
fun record(
|
||||||
|
error: JsonRpcException,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream
|
||||||
|
)
|
||||||
fun getSignature(): ResponseSigner.Signature?
|
fun getSignature(): ResponseSigner.Signature?
|
||||||
|
|
||||||
|
fun getProvidedUpstreamId(): String?
|
||||||
fun getResult(): ByteArray?
|
fun getResult(): ByteArray?
|
||||||
fun getError(): JsonRpcError?
|
fun getError(): JsonRpcError?
|
||||||
fun getResolvedBy(): Collection<Upstream>
|
fun getResolvedBy(): Collection<Upstream>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ open class NonEmptyQuorum(
|
|||||||
private var result: ByteArray? = null
|
private var result: ByteArray? = null
|
||||||
private var tries: Int = 0
|
private var tries: Int = 0
|
||||||
private var sig: ResponseSigner.Signature? = null
|
private var sig: ResponseSigner.Signature? = null
|
||||||
|
private var providedUpstreamId: String? = null
|
||||||
override fun init(head: Head) {
|
override fun init(head: Head) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,11 +43,22 @@ open class NonEmptyQuorum(
|
|||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordValue(response: ByteArray, responseValue: Any?, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun getProvidedUpstreamId(): String? {
|
||||||
|
return providedUpstreamId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recordValue(
|
||||||
|
response: ByteArray,
|
||||||
|
responseValue: Any?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
) {
|
||||||
tries++
|
tries++
|
||||||
if (responseValue != null) {
|
if (responseValue != null) {
|
||||||
result = response
|
result = response
|
||||||
sig = signature
|
sig = signature
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +66,13 @@ open class NonEmptyQuorum(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordError(response: ByteArray?, errorMessage: String?, sig: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun recordError(
|
||||||
|
response: ByteArray?,
|
||||||
|
errorMessage: String?,
|
||||||
|
sig: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
) {
|
||||||
tries++
|
tries++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ open class NonceQuorum(
|
|||||||
private var receivedTimes = 0
|
private var receivedTimes = 0
|
||||||
private var errors = 0
|
private var errors = 0
|
||||||
private var sig: ResponseSigner.Signature? = null
|
private var sig: ResponseSigner.Signature? = null
|
||||||
|
private var providedUpstreamId: String? = null
|
||||||
|
|
||||||
override fun init(head: Head) {
|
override fun init(head: Head) {
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,17 @@ open class NonceQuorum(
|
|||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordValue(response: ByteArray, responseValue: String?, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun getProvidedUpstreamId(): String? {
|
||||||
|
return providedUpstreamId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recordValue(
|
||||||
|
response: ByteArray,
|
||||||
|
responseValue: String?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
) {
|
||||||
val value = responseValue?.let { str ->
|
val value = responseValue?.let { str ->
|
||||||
HexQuantity.from(str).value.toLong()
|
HexQuantity.from(str).value.toLong()
|
||||||
}
|
}
|
||||||
@@ -60,9 +71,11 @@ open class NonceQuorum(
|
|||||||
resultValue = value
|
resultValue = value
|
||||||
result = response
|
result = response
|
||||||
sig = signature
|
sig = signature
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
} else if (result == null) {
|
} else if (result == null) {
|
||||||
result = response
|
result = response
|
||||||
sig = signature
|
sig = signature
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +84,13 @@ open class NonceQuorum(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun recordError(response: ByteArray?, errorMessage: String?, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun recordError(
|
||||||
|
response: ByteArray?,
|
||||||
|
errorMessage: String?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
) {
|
||||||
errors++
|
errors++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class NotLaggingQuorum(val maxLag: Long = 0) : CallQuorum {
|
|||||||
private var rpcError: JsonRpcError? = null
|
private var rpcError: JsonRpcError? = null
|
||||||
private var sig: ResponseSigner.Signature? = null
|
private var sig: ResponseSigner.Signature? = null
|
||||||
private val resolvers: MutableCollection<Upstream> = ConcurrentLinkedQueue()
|
private val resolvers: MutableCollection<Upstream> = ConcurrentLinkedQueue()
|
||||||
|
private var providedUpstreamId: String? = null
|
||||||
|
|
||||||
override fun init(head: Head) {
|
override fun init(head: Head) {
|
||||||
}
|
}
|
||||||
@@ -48,18 +49,28 @@ class NotLaggingQuorum(val maxLag: Long = 0) : CallQuorum {
|
|||||||
return failed.get()
|
return failed.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun record(response: ByteArray, signature: ResponseSigner.Signature?, upstream: Upstream): Boolean {
|
override fun record(
|
||||||
|
response: ByteArray,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
): Boolean {
|
||||||
val lagging = upstream.getLag() > maxLag
|
val lagging = upstream.getLag() > maxLag
|
||||||
if (!lagging) {
|
if (!lagging) {
|
||||||
result.set(response)
|
result.set(response)
|
||||||
sig = signature
|
sig = signature
|
||||||
|
this.providedUpstreamId = providedUpstreamId
|
||||||
resolvers.add(upstream)
|
resolvers.add(upstream)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun record(error: JsonRpcException, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun record(
|
||||||
|
error: JsonRpcException,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream
|
||||||
|
) {
|
||||||
this.rpcError = error.error
|
this.rpcError = error.error
|
||||||
val lagging = upstream.getLag() > maxLag
|
val lagging = upstream.getLag() > maxLag
|
||||||
if (!lagging && result.get() == null) {
|
if (!lagging && result.get() == null) {
|
||||||
@@ -70,6 +81,11 @@ class NotLaggingQuorum(val maxLag: Long = 0) : CallQuorum {
|
|||||||
override fun getSignature(): ResponseSigner.Signature? {
|
override fun getSignature(): ResponseSigner.Signature? {
|
||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getProvidedUpstreamId(): String? {
|
||||||
|
return providedUpstreamId
|
||||||
|
}
|
||||||
|
|
||||||
override fun getResult(): ByteArray {
|
override fun getResult(): ByteArray {
|
||||||
return result.get()
|
return result.get()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import io.emeraldpay.etherjar.rpc.RpcException
|
|||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import reactor.util.function.Tuple2
|
|
||||||
import reactor.util.function.Tuple3
|
import reactor.util.function.Tuple3
|
||||||
|
import reactor.util.function.Tuple4
|
||||||
import reactor.util.function.Tuples
|
import reactor.util.function.Tuples
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
@@ -90,8 +90,8 @@ class QuorumRpcReader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun execute(key: JsonRpcRequest, retrySpec: reactor.util.retry.Retry): Function<Flux<Upstream>, Mono<CallQuorum>> {
|
fun execute(key: JsonRpcRequest, retrySpec: reactor.util.retry.Retry): Function<Flux<Upstream>, Mono<CallQuorum>> {
|
||||||
val quorumReduce = BiFunction<CallQuorum, Tuple3<ByteArray, Optional<ResponseSigner.Signature>, Upstream>, CallQuorum> { res, a ->
|
val quorumReduce = BiFunction<CallQuorum, Tuple4<ByteArray, Optional<ResponseSigner.Signature>, Upstream, Optional<String>>, CallQuorum> { res, a ->
|
||||||
if (res.record(a.t1, a.t2.orElse(null), a.t3)) {
|
if (res.record(a.t1, a.t2.orElse(null), a.t3, a.t4.orElse(null))) {
|
||||||
apiControl.resolve()
|
apiControl.resolve()
|
||||||
} else {
|
} else {
|
||||||
// quorum needs more responses, so ask api controller to make another
|
// quorum needs more responses, so ask api controller to make another
|
||||||
@@ -119,25 +119,25 @@ class QuorumRpcReader(
|
|||||||
.filter { it.isResolved() } // return nothing if not resolved
|
.filter { it.isResolved() } // return nothing if not resolved
|
||||||
.map { quorum ->
|
.map { quorum ->
|
||||||
// TODO find actual quorum number
|
// TODO find actual quorum number
|
||||||
Result(quorum.getResult()!!, quorum.getSignature(), 1, quorum.getResolvedBy())
|
Result(quorum.getResult()!!, quorum.getSignature(), 1, quorum.getResolvedBy(), quorum.getProvidedUpstreamId())
|
||||||
}
|
}
|
||||||
.switchIfEmpty(defaultResult)
|
.switchIfEmpty(defaultResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun callApi(api: Upstream, key: JsonRpcRequest): Mono<Tuple3<ByteArray, Optional<ResponseSigner.Signature>, Upstream>> {
|
fun callApi(api: Upstream, key: JsonRpcRequest): Mono<Tuple4<ByteArray, Optional<ResponseSigner.Signature>, Upstream, Optional<String>>> {
|
||||||
return api.getIngressReader()
|
return api.getIngressReader()
|
||||||
.read(key)
|
.read(key)
|
||||||
.flatMap { response ->
|
.flatMap { response ->
|
||||||
response.requireResult()
|
response.requireResult()
|
||||||
.transform(withSignature(api, key, response))
|
.transform(withSignatureAndUpstream(api, key, response))
|
||||||
}
|
}
|
||||||
// must catch not only the processing of a response but also errors thrown from the .read() call
|
// must catch not only the processing of a response but also errors thrown from the .read() call
|
||||||
.transform(withErrorResume(api, key))
|
.transform(withErrorResume(api, key))
|
||||||
.map { Tuples.of(it.t1, it.t2, api) }
|
.map { Tuples.of(it.t1, it.t2, api, it.t3) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withSignature(api: Upstream, key: JsonRpcRequest, response: JsonRpcResponse): Function<Mono<ByteArray>, Mono<Tuple2<ByteArray, Optional<ResponseSigner.Signature>>>> {
|
fun withSignatureAndUpstream(api: Upstream, key: JsonRpcRequest, response: JsonRpcResponse): Function<Mono<ByteArray>, Mono<Tuple3<ByteArray, Optional<ResponseSigner.Signature>, Optional<String>>>> {
|
||||||
return Function { src ->
|
return Function { src ->
|
||||||
src.map {
|
src.map {
|
||||||
val signature = response.providedSignature
|
val signature = response.providedSignature
|
||||||
@@ -146,7 +146,7 @@ class QuorumRpcReader(
|
|||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
Tuples.of(it, Optional.ofNullable(signature))
|
Tuples.of(it, Optional.ofNullable(signature), Optional.ofNullable(response.providedUpstreamId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ class QuorumRpcReader(
|
|||||||
JsonRpcError(-32603, "Unhandled internal error: ${err.javaClass}: ${err.message}")
|
JsonRpcError(-32603, "Unhandled internal error: ${err.javaClass}: ${err.message}")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
quorum.record(cleanErr, null, api)
|
quorum.record(cleanErr, null, api,)
|
||||||
// if it's failed after that, then we don't need more calls, stop api source
|
// if it's failed after that, then we don't need more calls, stop api source
|
||||||
if (quorum.isFailed()) {
|
if (quorum.isFailed()) {
|
||||||
apiControl.resolve()
|
apiControl.resolve()
|
||||||
@@ -198,6 +198,7 @@ class QuorumRpcReader(
|
|||||||
val value: ByteArray,
|
val value: ByteArray,
|
||||||
val signature: ResponseSigner.Signature?,
|
val signature: ResponseSigner.Signature?,
|
||||||
val quorum: Int,
|
val quorum: Int,
|
||||||
val resolvers: Collection<Upstream>
|
val resolvers: Collection<Upstream>,
|
||||||
|
val providedUpstreamId: String?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,27 +37,48 @@ abstract class ValueAwareQuorum<T>(
|
|||||||
return Global.objectMapper.readValue(response.inputStream(), clazz)
|
return Global.objectMapper.readValue(response.inputStream(), clazz)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun record(response: ByteArray, signature: ResponseSigner.Signature?, upstream: Upstream): Boolean {
|
override fun record(
|
||||||
|
response: ByteArray,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
): Boolean {
|
||||||
try {
|
try {
|
||||||
val value = extractValue(response, clazz)
|
val value = extractValue(response, clazz)
|
||||||
recordValue(response, value, signature, upstream)
|
recordValue(response, value, signature, upstream, providedUpstreamId)
|
||||||
resolvers.add(upstream)
|
resolvers.add(upstream)
|
||||||
} catch (e: RpcException) {
|
} catch (e: RpcException) {
|
||||||
recordError(response, e.rpcMessage, signature, upstream)
|
recordError(response, e.rpcMessage, signature, upstream, providedUpstreamId)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
recordError(response, e.message, signature, upstream)
|
recordError(response, e.message, signature, upstream, providedUpstreamId)
|
||||||
}
|
}
|
||||||
return isResolved()
|
return isResolved()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun record(error: JsonRpcException, signature: ResponseSigner.Signature?, upstream: Upstream) {
|
override fun record(
|
||||||
|
error: JsonRpcException,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream
|
||||||
|
) {
|
||||||
this.rpcError = error.error
|
this.rpcError = error.error
|
||||||
recordError(null, error.error.message, signature, upstream)
|
recordError(null, error.error.message, signature, upstream, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun recordValue(response: ByteArray, responseValue: T?, signature: ResponseSigner.Signature?, upstream: Upstream)
|
abstract fun recordValue(
|
||||||
|
response: ByteArray,
|
||||||
|
responseValue: T?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
)
|
||||||
|
|
||||||
abstract fun recordError(response: ByteArray?, errorMessage: String?, signature: ResponseSigner.Signature?, upstream: Upstream)
|
abstract fun recordError(
|
||||||
|
response: ByteArray?,
|
||||||
|
errorMessage: String?,
|
||||||
|
signature: ResponseSigner.Signature?,
|
||||||
|
upstream: Upstream,
|
||||||
|
providedUpstreamId: String?
|
||||||
|
)
|
||||||
|
|
||||||
override fun getError(): JsonRpcError? {
|
override fun getError(): JsonRpcError? {
|
||||||
return rpcError
|
return rpcError
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ open class NativeCall(
|
|||||||
.map {
|
.map {
|
||||||
val bytes = ctx.resultDecorator.processResult(it)
|
val bytes = ctx.resultDecorator.processResult(it)
|
||||||
validateResult(bytes, "remote", ctx)
|
validateResult(bytes, "remote", ctx)
|
||||||
CallResult.ok(ctx.id, ctx.nonce, bytes, it.signature, it.resolvers.first().getId(), ctx)
|
CallResult.ok(ctx.id, ctx.nonce, bytes, it.signature, it.providedUpstreamId ?: it.resolvers.first().getId(), ctx)
|
||||||
}
|
}
|
||||||
.onErrorResume { t ->
|
.onErrorResume { t ->
|
||||||
Mono.just(CallResult.fail(ctx.id, ctx.nonce, t, ctx))
|
Mono.just(CallResult.fail(ctx.id, ctx.nonce, t, ctx))
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class JsonRpcGrpcClient(
|
|||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
Mono.just(JsonRpcResponse(bytes, null, JsonRpcResponse.NumberId(0), signature))
|
Mono.just(JsonRpcResponse(bytes, null, JsonRpcResponse.NumberId(0), signature, resp.upstreamId))
|
||||||
} else {
|
} else {
|
||||||
metrics?.fails?.increment()
|
metrics?.fails?.increment()
|
||||||
Mono.error(
|
Mono.error(
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ class JsonRpcResponse(
|
|||||||
/**
|
/**
|
||||||
* When making a request through Dshackle protocol a remote may provide its signature with the response, which we keep here
|
* When making a request through Dshackle protocol a remote may provide its signature with the response, which we keep here
|
||||||
*/
|
*/
|
||||||
val providedSignature: ResponseSigner.Signature? = null
|
val providedSignature: ResponseSigner.Signature? = null,
|
||||||
|
val providedUpstreamId: String? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(result: ByteArray?, error: JsonRpcError?) : this(result, error, NumberId(0))
|
constructor(result: ByteArray?, error: JsonRpcError?) : this(result, error, NumberId(0))
|
||||||
@@ -113,11 +114,7 @@ class JsonRpcResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun copyWithId(id: Id): JsonRpcResponse {
|
fun copyWithId(id: Id): JsonRpcResponse {
|
||||||
return JsonRpcResponse(result, error, id, providedSignature)
|
return JsonRpcResponse(result, error, id, providedSignature, providedUpstreamId)
|
||||||
}
|
|
||||||
|
|
||||||
fun copyWithSignature(signature: ResponseSigner.Signature): JsonRpcResponse {
|
|
||||||
return JsonRpcResponse(result, error, id, signature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class AlwaysQuorumSpec extends Specification {
|
|||||||
def quorum = new AlwaysQuorum()
|
def quorum = new AlwaysQuorum()
|
||||||
def up = Stub(Upstream)
|
def up = Stub(Upstream)
|
||||||
when:
|
when:
|
||||||
quorum.record("123".bytes, new ResponseSigner.Signature("sig1".bytes, "test", 100), up)
|
quorum.record("123".bytes, new ResponseSigner.Signature("sig1".bytes, "test", 100), up, null)
|
||||||
then:
|
then:
|
||||||
quorum.isResolved()
|
quorum.isResolved()
|
||||||
quorum.getResult() == "123".bytes
|
quorum.getResult() == "123".bytes
|
||||||
|
|||||||
@@ -43,21 +43,21 @@ class BroadcastQuorumSpec extends Specification {
|
|||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"'.bytes, null, upstream1)
|
q.record('"0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"'.bytes, null, upstream1, null)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _, _)
|
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"'.bytes, null, upstream2)
|
q.record('"0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"'.bytes, null, upstream2, null)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _, _)
|
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record(new JsonRpcException(1, "Nonce too low"), null, upstream3)
|
q.record(new JsonRpcException(1, "Nonce too low"), null, upstream3)
|
||||||
then:
|
then:
|
||||||
1 * q.recordError(_, _, _, _)
|
1 * q.recordError(_, _, _, _, _)
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
objectMapper.readValue(q.result, Object) == "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"
|
objectMapper.readValue(q.result, Object) == "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"
|
||||||
}
|
}
|
||||||
@@ -78,18 +78,18 @@ class BroadcastQuorumSpec extends Specification {
|
|||||||
q.record(new JsonRpcException(1, "Internal error"), null, upstream1)
|
q.record(new JsonRpcException(1, "Internal error"), null, upstream1)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordError(_, _, _, _)
|
1 * q.recordError(_, _, _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"'.bytes, null, upstream2)
|
q.record('"0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"'.bytes, null, upstream2, null)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _, _)
|
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record(new JsonRpcException(1, "Nonce too low"), null, upstream3)
|
q.record(new JsonRpcException(1, "Nonce too low"), null, upstream3)
|
||||||
then:
|
then:
|
||||||
1 * q.recordError(_, _, _, _)
|
1 * q.recordError(_, _, _, _, _)
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
objectMapper.readValue(q.result, Object) == "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"
|
objectMapper.readValue(q.result, Object) == "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,6 @@ class NonEmptyQuorumSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def q = Spy(new NonEmptyQuorum(3))
|
def q = Spy(new NonEmptyQuorum(3))
|
||||||
def upstream1 = Stub(Upstream)
|
def upstream1 = Stub(Upstream)
|
||||||
def upstream2 = Stub(Upstream)
|
|
||||||
def upstream3 = Stub(Upstream)
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.init(Stub(Head))
|
q.init(Stub(Head))
|
||||||
@@ -71,7 +69,7 @@ class NonEmptyQuorumSpec extends Specification {
|
|||||||
!q.isFailed()
|
!q.isFailed()
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x11"'.bytes, null, upstream1)
|
q.record('"0x11"'.bytes, null, upstream1, null)
|
||||||
then:
|
then:
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
!q.isFailed()
|
!q.isFailed()
|
||||||
@@ -82,7 +80,6 @@ class NonEmptyQuorumSpec extends Specification {
|
|||||||
def q = Spy(new NonEmptyQuorum(3))
|
def q = Spy(new NonEmptyQuorum(3))
|
||||||
def upstream1 = Stub(Upstream)
|
def upstream1 = Stub(Upstream)
|
||||||
def upstream2 = Stub(Upstream)
|
def upstream2 = Stub(Upstream)
|
||||||
def upstream3 = Stub(Upstream)
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.init(Stub(Head))
|
q.init(Stub(Head))
|
||||||
@@ -98,7 +95,7 @@ class NonEmptyQuorumSpec extends Specification {
|
|||||||
q.signature == null
|
q.signature == null
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x11"'.bytes, null, upstream2)
|
q.record('"0x11"'.bytes, null, upstream2, null)
|
||||||
then:
|
then:
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
!q.isFailed()
|
!q.isFailed()
|
||||||
@@ -108,8 +105,6 @@ class NonEmptyQuorumSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def q = Spy(new NonEmptyQuorum(3))
|
def q = Spy(new NonEmptyQuorum(3))
|
||||||
def upstream1 = Stub(Upstream)
|
def upstream1 = Stub(Upstream)
|
||||||
def upstream2 = Stub(Upstream)
|
|
||||||
def upstream3 = Stub(Upstream)
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.init(Stub(Head))
|
q.init(Stub(Head))
|
||||||
@@ -118,14 +113,14 @@ class NonEmptyQuorumSpec extends Specification {
|
|||||||
!q.isFailed()
|
!q.isFailed()
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('null'.bytes, null, upstream2)
|
q.record('null'.bytes, null, upstream1, null)
|
||||||
then:
|
then:
|
||||||
!q.isFailed()
|
!q.isFailed()
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x11"'.bytes, null, upstream2)
|
q.record('"0x11"'.bytes, null, upstream1, null)
|
||||||
then:
|
then:
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
!q.isFailed()
|
!q.isFailed()
|
||||||
|
|||||||
@@ -18,12 +18,9 @@ package io.emeraldpay.dshackle.quorum
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.emeraldpay.dshackle.Global
|
import io.emeraldpay.dshackle.Global
|
||||||
import io.emeraldpay.dshackle.test.TestingCommons
|
|
||||||
import io.emeraldpay.dshackle.upstream.Head
|
import io.emeraldpay.dshackle.upstream.Head
|
||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.quorum.NonceQuorum
|
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
||||||
import io.emeraldpay.etherjar.rpc.RpcException
|
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
class NonceQuorumSpec extends Specification {
|
class NonceQuorumSpec extends Specification {
|
||||||
@@ -43,21 +40,21 @@ class NonceQuorumSpec extends Specification {
|
|||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x10"'.bytes, null, upstream1)
|
q.record('"0x10"'.bytes, null, upstream1, null)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordValue(_, "0x10", _, _)
|
1 * q.recordValue(_, "0x10", _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x11"'.bytes, null, upstream2)
|
q.record('"0x11"'.bytes, null, upstream2, null)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordValue(_, "0x11", _, _)
|
1 * q.recordValue(_, "0x11", _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x10"'.bytes, null, upstream3)
|
q.record('"0x10"'.bytes, null, upstream3, null)
|
||||||
then:
|
then:
|
||||||
1 * q.recordValue(_, "0x10", _, _)
|
1 * q.recordValue(_, "0x10", _, _, _)
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
objectMapper.readValue(q.result, Object) == "0x11"
|
objectMapper.readValue(q.result, Object) == "0x11"
|
||||||
}
|
}
|
||||||
@@ -78,24 +75,24 @@ class NonceQuorumSpec extends Specification {
|
|||||||
q.record(new JsonRpcException(1, "Internal"), null, upstream1)
|
q.record(new JsonRpcException(1, "Internal"), null, upstream1)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordError(_, _, _, _)
|
1 * q.recordError(_, _, _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x11"'.bytes, null, upstream2)
|
q.record('"0x11"'.bytes, null, upstream2, null)
|
||||||
then:
|
then:
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
1 * q.recordValue(_, "0x11", _, _)
|
1 * q.recordValue(_, "0x11", _, _, _)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x10"'.bytes, null, upstream3)
|
q.record('"0x10"'.bytes, null, upstream3, null)
|
||||||
then:
|
then:
|
||||||
1 * q.recordValue(_, "0x10", _, _)
|
1 * q.recordValue(_, "0x10", _, _, _)
|
||||||
!q.isResolved()
|
!q.isResolved()
|
||||||
|
|
||||||
when:
|
when:
|
||||||
q.record('"0x11"'.bytes, null, upstream1)
|
q.record('"0x11"'.bytes, null, upstream1, null)
|
||||||
then:
|
then:
|
||||||
1 * q.recordValue(_, "0x11", _, _)
|
1 * q.recordValue(_, "0x11", _, _, _)
|
||||||
q.isResolved()
|
q.isResolved()
|
||||||
objectMapper.readValue(q.result, Object) == "0x11"
|
objectMapper.readValue(q.result, Object) == "0x11"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class NotLaggingQuorumSpec extends Specification {
|
|||||||
def quorum = new NotLaggingQuorum(1)
|
def quorum = new NotLaggingQuorum(1)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
quorum.record(value, null, up)
|
quorum.record(value, null, up, null)
|
||||||
then:
|
then:
|
||||||
1 * up.getLag() >> 0
|
1 * up.getLag() >> 0
|
||||||
quorum.isResolved()
|
quorum.isResolved()
|
||||||
@@ -40,20 +40,21 @@ class NotLaggingQuorumSpec extends Specification {
|
|||||||
quorum.result == value
|
quorum.result == value
|
||||||
}
|
}
|
||||||
|
|
||||||
def "Keeps signature"() {
|
def "Keeps signature and upstream"() {
|
||||||
setup:
|
setup:
|
||||||
def up = Mock(Upstream)
|
def up = Mock(Upstream)
|
||||||
def value = "foo".getBytes()
|
def value = "foo".getBytes()
|
||||||
def quorum = new NotLaggingQuorum(1)
|
def quorum = new NotLaggingQuorum(1)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
quorum.record(value, new ResponseSigner.Signature("sig1".bytes, "test", 100), up)
|
quorum.record(value, new ResponseSigner.Signature("sig1".bytes, "test", 100), up, "test")
|
||||||
then:
|
then:
|
||||||
1 * up.getLag() >> 0
|
1 * up.getLag() >> 0
|
||||||
quorum.isResolved()
|
quorum.isResolved()
|
||||||
!quorum.isFailed()
|
!quorum.isFailed()
|
||||||
quorum.result == value
|
quorum.result == value
|
||||||
quorum.signature == new ResponseSigner.Signature("sig1".bytes, "test", 100)
|
quorum.signature == new ResponseSigner.Signature("sig1".bytes, "test", 100)
|
||||||
|
quorum.providedUpstreamId == "test"
|
||||||
}
|
}
|
||||||
|
|
||||||
def "Resolves if ok lag"() {
|
def "Resolves if ok lag"() {
|
||||||
@@ -63,7 +64,7 @@ class NotLaggingQuorumSpec extends Specification {
|
|||||||
def quorum = new NotLaggingQuorum(1)
|
def quorum = new NotLaggingQuorum(1)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
quorum.record(value, null, up)
|
quorum.record(value, null, up, null)
|
||||||
then:
|
then:
|
||||||
1 * up.getLag() >> 1
|
1 * up.getLag() >> 1
|
||||||
quorum.isResolved()
|
quorum.isResolved()
|
||||||
@@ -78,7 +79,7 @@ class NotLaggingQuorumSpec extends Specification {
|
|||||||
def quorum = new NotLaggingQuorum(1)
|
def quorum = new NotLaggingQuorum(1)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
quorum.record(value, null, up)
|
quorum.record(value, null, up, null)
|
||||||
then:
|
then:
|
||||||
1 * up.getLag() >> 2
|
1 * up.getLag() >> 2
|
||||||
!quorum.isResolved()
|
!quorum.isResolved()
|
||||||
|
|||||||
@@ -66,14 +66,14 @@ class ValueAwareQuorumSpec extends Specification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void recordValue(@NotNull byte[] response, @Nullable Object responseValue, @Nullable ResponseSigner.Signature signature, @NotNull Upstream upstream) {
|
void recordValue(@NotNull byte[] response, @Nullable Object responseValue, @Nullable ResponseSigner.Signature signature, @NotNull Upstream upstream, @Nullable String providedUpstreamId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void recordError(@Nullable byte[] response, @Nullable String errorMessage, @Nullable ResponseSigner.Signature signature, @NotNull Upstream upstream) {
|
void recordError(@Nullable byte[] response, @Nullable String errorMessage, @Nullable ResponseSigner.Signature signature, @NotNull Upstream upstream, @Nullable String providedUpstreamId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,5 +101,10 @@ class ValueAwareQuorumSpec extends Specification {
|
|||||||
boolean isFailed() {
|
boolean isFailed() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getProvidedUpstreamId() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ class NativeCallSpec extends Specification {
|
|||||||
def nativeCall = nativeCall()
|
def nativeCall = nativeCall()
|
||||||
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"foo\"".bytes, null, 1, Collections.singletonList(ups)))
|
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"foo\"".bytes, null, 1, Collections.singletonList(ups), null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
|
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), Selector.empty, quorum,
|
||||||
@@ -613,7 +613,7 @@ class NativeCallSpec extends Specification {
|
|||||||
def nativeCall = nativeCall(multistreamHolder)
|
def nativeCall = nativeCall(multistreamHolder)
|
||||||
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList(ups)))
|
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList(ups), null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum,
|
def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum,
|
||||||
@@ -648,7 +648,7 @@ class NativeCallSpec extends Specification {
|
|||||||
def nativeCall = nativeCall(multistreamHolder)
|
def nativeCall = nativeCall(multistreamHolder)
|
||||||
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
nativeCall.quorumReaderFactory = Mock(QuorumReaderFactory) {
|
||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList(ups)))
|
1 * read(_) >> Mono.just(new QuorumRpcReader.Result("\"0xab\"".bytes, null, 1, Collections.singletonList(ups), null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum,
|
def call = new NativeCall.ValidCallContext(1, 10, multistream, Selector.empty, quorum,
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class ApiReaderMock implements Reader<JsonRpcRequest, JsonRpcResponse> {
|
|||||||
}
|
}
|
||||||
error = new JsonRpcError(-32601, "Method ${request.method} with ${request.params} is not mocked")
|
error = new JsonRpcError(-32601, "Method ${request.method} with ${request.params} is not mocked")
|
||||||
}
|
}
|
||||||
return new JsonRpcResponse(result, error, JsonRpcResponse.Id.from(request.id), null)
|
return new JsonRpcResponse(result, error, JsonRpcResponse.Id.from(request.id), null, null)
|
||||||
} as Callable<JsonRpcResponse>
|
} as Callable<JsonRpcResponse>
|
||||||
return Mono.fromCallable(call)
|
return Mono.fromCallable(call)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(json), null, 1, resolvers)
|
Global.objectMapper.writeValueAsBytes(json), null, 1, resolvers, null)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getBlockByHash", [hash1, false])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(null), null, 1, resolvers
|
Global.objectMapper.writeValueAsBytes(null), null, 1, resolvers, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x64", false])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getBlockByNumber", ["0x64", false])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(json), null, 1, resolvers
|
Global.objectMapper.writeValueAsBytes(json), null, 1, resolvers, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getTransactionByHash", [hash1])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getTransactionByHash", [hash1])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(json), null, 1, resolvers
|
Global.objectMapper.writeValueAsBytes(json), null, 1, resolvers, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getTransactionReceipt", [hash1])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getTransactionReceipt", [hash1])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(json), null, 1, new ArrayList<Byte>()
|
Global.objectMapper.writeValueAsBytes(json), null, 1, new ArrayList<Byte>(), null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getTransactionReceipt", [hash1])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getTransactionReceipt", [hash1])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(json), null, 1, new ArrayList<Byte>()
|
Global.objectMapper.writeValueAsBytes(json), null, 1, new ArrayList<Byte>(), null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getTransactionByHash", [hash1])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getTransactionByHash", [hash1])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes(null), null, 1, resolvers
|
Global.objectMapper.writeValueAsBytes(null), null, 1, resolvers, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getBalance", [address1, "latest"])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getBalance", [address1, "latest"])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes("0x100"), null, 1, resolvers
|
Global.objectMapper.writeValueAsBytes("0x100"), null, 1, resolvers, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ class EthereumDirectReaderSpec extends Specification {
|
|||||||
1 * create(_, _, _) >> Mock(Reader) {
|
1 * create(_, _, _) >> Mock(Reader) {
|
||||||
1 * read(new JsonRpcRequest("eth_getBalance", [address1, "0xa8c9bb"])) >> Mono.just(
|
1 * read(new JsonRpcRequest("eth_getBalance", [address1, "0xa8c9bb"])) >> Mono.just(
|
||||||
new QuorumRpcReader.Result(
|
new QuorumRpcReader.Result(
|
||||||
Global.objectMapper.writeValueAsBytes("0x100"), null, 1, resolvers
|
Global.objectMapper.writeValueAsBytes("0x100"), null, 1, resolvers, null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize int id and null result"() {
|
def "Serialize int id and null result"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse("null".bytes, null, new JsonRpcResponse.NumberId(1), null)
|
def json = new JsonRpcResponse("null".bytes, null, new JsonRpcResponse.NumberId(1), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -72,7 +72,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize int id and string result"() {
|
def "Serialize int id and string result"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse('"Hello World"'.bytes, null, new JsonRpcResponse.NumberId(10), null)
|
def json = new JsonRpcResponse('"Hello World"'.bytes, null, new JsonRpcResponse.NumberId(10), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -81,7 +81,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize int id and object result"() {
|
def "Serialize int id and object result"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new JsonRpcResponse.NumberId(101), null)
|
def json = new JsonRpcResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new JsonRpcResponse.NumberId(101), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -90,7 +90,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize int id and error"() {
|
def "Serialize int id and error"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse(null, new JsonRpcError(-32041, "Oooops"), new JsonRpcResponse.NumberId(101), null)
|
def json = new JsonRpcResponse(null, new JsonRpcError(-32041, "Oooops"), new JsonRpcResponse.NumberId(101), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -99,7 +99,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize string id and null result"() {
|
def "Serialize string id and null result"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse("null".bytes, null, new JsonRpcResponse.StringId("asf01t1gg"), null)
|
def json = new JsonRpcResponse("null".bytes, null, new JsonRpcResponse.StringId("asf01t1gg"), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -108,7 +108,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize string id and string result"() {
|
def "Serialize string id and string result"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse('"Hello World"'.bytes, null, new JsonRpcResponse.StringId("10"), null)
|
def json = new JsonRpcResponse('"Hello World"'.bytes, null, new JsonRpcResponse.StringId("10"), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -117,7 +117,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
|
|
||||||
def "Serialize string id and object result"() {
|
def "Serialize string id and object result"() {
|
||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new JsonRpcResponse.StringId("g8gk19g"), null)
|
def json = new JsonRpcResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new JsonRpcResponse.StringId("g8gk19g"), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
@@ -128,7 +128,7 @@ class JsonRpcResponseSpec extends Specification {
|
|||||||
setup:
|
setup:
|
||||||
def json = new JsonRpcResponse(null,
|
def json = new JsonRpcResponse(null,
|
||||||
new JsonRpcError(-32041, "Oooops"),
|
new JsonRpcError(-32041, "Oooops"),
|
||||||
new JsonRpcResponse.StringId("9kbo29gkaasf"), null)
|
new JsonRpcResponse.StringId("9kbo29gkaasf"), null, null)
|
||||||
when:
|
when:
|
||||||
def act = objectMapper.writeValueAsString(json)
|
def act = objectMapper.writeValueAsString(json)
|
||||||
then:
|
then:
|
||||||
|
|||||||
Reference in New Issue
Block a user