Pass all upstreams that resolved a request (#531)
This commit is contained in:
@@ -116,7 +116,7 @@ abstract class BaseHandler(
|
||||
// If Proxy is configured to preserve original order it means that a client expect responses at exact same position
|
||||
// as requests even if a request completely failed for a some reason. It's very unlikely situation, but still possible
|
||||
// At this case, if we found a gap in responses, we put a default response with an error
|
||||
?: NativeCall.CallResult(id, null, null, NativeCall.CallError(id, "No response", null, null), null, null, null)
|
||||
?: NativeCall.CallResult(id, null, null, NativeCall.CallError(id, "No response", null, null), null, emptyList(), null)
|
||||
}
|
||||
}
|
||||
.flatMapMany {
|
||||
|
||||
@@ -183,7 +183,7 @@ class WebsocketHandler(
|
||||
}
|
||||
Mono.just(response)
|
||||
.map { Global.objectMapper.writeValueAsString(it) }
|
||||
.doOnNext { eventHandler.onResponse(NativeCall.CallResult.ok(0, null, it.toByteArray(), null, null, null)) }
|
||||
.doOnNext { eventHandler.onResponse(NativeCall.CallResult.ok(0, null, it.toByteArray(), null, emptyList(), null)) }
|
||||
.doFinally { eventHandler.close() }
|
||||
} else {
|
||||
val eventHandler: AccessHandlerHttp.RequestHandler = eventHandlerFactory.call()
|
||||
|
||||
@@ -223,8 +223,12 @@ class QuorumRequestReader(
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolvedBy() =
|
||||
if (quorum.getResolvedBy().isEmpty()) null else quorum.getResolvedBy().last().getUpstreamSettingsData()
|
||||
private fun resolvedBy(): List<Upstream.UpstreamSettingsData> {
|
||||
if (quorum.getResolvedBy().isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
return quorum.getResolvedBy().last().getUpstreamSettingsData()?.run { listOf(this) } ?: emptyList()
|
||||
}
|
||||
|
||||
private fun noResponse(method: String, q: CallQuorum): Mono<Result> {
|
||||
return apiControl.upstreamsMatchesResponse()?.run {
|
||||
@@ -232,7 +236,7 @@ class QuorumRequestReader(
|
||||
val cause = getCause(method) ?: return Mono.error(RpcException(1, "No response for method $method", getFullCause()))
|
||||
if (cause.shouldReturnNull) {
|
||||
Mono.just(
|
||||
Result(Global.nullValue, null, 1, null, null),
|
||||
Result(Global.nullValue, null, 1, emptyList(), null),
|
||||
)
|
||||
} else {
|
||||
Mono.error(RpcException(1, "No response for method $method. Cause - ${cause.cause}"))
|
||||
|
||||
@@ -46,26 +46,28 @@ class BroadcastReader(
|
||||
val sig = getSignature(key, it.jsonRpcResponse, it.upstream.getId())
|
||||
quorum.record(it.jsonRpcResponse, sig, it.upstream)
|
||||
} else {
|
||||
val err = ChainException(ChainResponse.NumberId(key.id), it.jsonRpcResponse.error!!, it.upstream.getUpstreamSettingsData())
|
||||
val upData = it.upstream.getUpstreamSettingsData()?.run { listOf(this) } ?: emptyList()
|
||||
val err = ChainException(ChainResponse.NumberId(key.id), it.jsonRpcResponse.error!!, upData)
|
||||
quorum.record(err, null, it.upstream)
|
||||
}
|
||||
quorum
|
||||
}.onErrorResume { err ->
|
||||
log.error("Broadcast error: ${err.message}")
|
||||
Mono.error(handleError(null, 0, null))
|
||||
Mono.error(handleError(null, 0, emptyList()))
|
||||
}.collectList()
|
||||
.flatMap {
|
||||
val upsData = quorum.getResolvedBy().mapNotNull { it.getUpstreamSettingsData() }
|
||||
if (quorum.isResolved()) {
|
||||
val res = Result(
|
||||
quorum.getResponse()!!.getResult(),
|
||||
quorum.getSignature(),
|
||||
upstreams.size,
|
||||
quorum.getResolvedBy().first().getUpstreamSettingsData(),
|
||||
upsData,
|
||||
null,
|
||||
)
|
||||
Mono.just(res)
|
||||
} else {
|
||||
Mono.error(handleError(quorum.getError(), key.id, null))
|
||||
Mono.error(handleError(quorum.getError(), key.id, upsData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,12 @@ abstract class RequestReader(
|
||||
)
|
||||
}
|
||||
|
||||
protected fun handleError(error: ChainCallError?, id: Int, upstreamSettingsData: Upstream.UpstreamSettingsData?) =
|
||||
error?.asException(ChainResponse.NumberId(id), upstreamSettingsData)
|
||||
?: ChainException(ChainResponse.NumberId(id), ChainCallError(-32603, "Unhandled Upstream error"), upstreamSettingsData)
|
||||
protected fun handleError(
|
||||
error: ChainCallError?,
|
||||
id: Int,
|
||||
upstreamSettingsData: List<Upstream.UpstreamSettingsData>,
|
||||
) = error?.asException(ChainResponse.NumberId(id), upstreamSettingsData)
|
||||
?: ChainException(ChainResponse.NumberId(id), ChainCallError(-32603, "Unhandled Upstream error"), upstreamSettingsData)
|
||||
|
||||
protected fun getSignature(key: ChainRequest, response: ChainResponse, upstreamId: String) =
|
||||
response.providedSignature
|
||||
@@ -50,7 +53,7 @@ abstract class RequestReader(
|
||||
val value: ByteArray,
|
||||
val signature: ResponseSigner.Signature?,
|
||||
val quorum: Int,
|
||||
val resolvedUpstreamData: Upstream.UpstreamSettingsData?,
|
||||
val resolvedUpstreamData: List<Upstream.UpstreamSettingsData>,
|
||||
val stream: Flux<Chunk>?,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,10 +138,15 @@ open class NativeCall(
|
||||
Flux.concat(
|
||||
Mono.just(firstChunk)
|
||||
.map {
|
||||
buildStreamResult(it, callResult.id)
|
||||
.setUpstreamId(callResult.upstreamSettingsData?.id)
|
||||
.setUpstreamNodeVersion(callResult.upstreamSettingsData?.nodeVersion)
|
||||
.build()
|
||||
val result = buildStreamResult(it, callResult.id)
|
||||
if (callResult.upstreamSettingsData.isNotEmpty()) {
|
||||
getUpstreamIdsAndVersions(callResult.upstreamSettingsData)
|
||||
.let { idsAndVersions ->
|
||||
result.upstreamId = idsAndVersions.first
|
||||
result.upstreamNodeVersion = idsAndVersions.second
|
||||
}
|
||||
}
|
||||
result.build()
|
||||
},
|
||||
stream.skip(1).map { buildStreamResult(it, callResult.id).build() },
|
||||
)
|
||||
@@ -213,7 +218,7 @@ open class NativeCall(
|
||||
val error = callContext.getError()
|
||||
|
||||
Mono.just(
|
||||
CallResult(error.id, 0, null, error, null, null, null),
|
||||
CallResult(error.id, 0, null, error, null, emptyList(), null),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -242,9 +247,10 @@ open class NativeCall(
|
||||
if (it.nonce != null && it.signature != null) {
|
||||
result.signature = buildSignature(it.nonce, it.signature)
|
||||
}
|
||||
it.upstreamSettingsData?.let {
|
||||
result.upstreamId = it.id
|
||||
result.upstreamNodeVersion = it.nodeVersion
|
||||
if (it.upstreamSettingsData.isNotEmpty()) {
|
||||
val idsAndVersions = getUpstreamIdsAndVersions(it.upstreamSettingsData)
|
||||
result.upstreamId = idsAndVersions.first
|
||||
result.upstreamNodeVersion = idsAndVersions.second
|
||||
}
|
||||
it.finalization?.let {
|
||||
result.finalization = Common.FinalizationData.newBuilder()
|
||||
@@ -397,6 +403,13 @@ open class NativeCall(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUpstreamIdsAndVersions(upstreamSettingsData: List<Upstream.UpstreamSettingsData>): Pair<String, String> {
|
||||
return Pair(
|
||||
upstreamSettingsData.joinToString { it.id },
|
||||
upstreamSettingsData.joinToString { it.nodeVersion },
|
||||
)
|
||||
}
|
||||
|
||||
private fun parsedCallDetails(item: BlockchainOuterClass.NativeCallItem): ParsedCallDetails {
|
||||
return if (item.hasPayload()) {
|
||||
ParsedCallDetails(item.method, extractParams(item.payload.toStringUtf8()))
|
||||
@@ -432,10 +445,17 @@ open class NativeCall(
|
||||
.read(ctx.payload.toChainRequest(ctx.nonce, ctx.forwardedSelector, false))
|
||||
.map {
|
||||
val result = it.getResult()
|
||||
val resolvedUpstreamData = it.resolvedUpstreamData ?: ctx.upstream.getUpstreamSettingsData()
|
||||
val resolvedUpstreamData = it.resolvedUpstreamData.ifEmpty {
|
||||
ctx.upstream.getUpstreamSettingsData()?.run { listOf(this) } ?: emptyList()
|
||||
}
|
||||
validateResult(result, "local", ctx)
|
||||
if (ctx.nonce != null) {
|
||||
CallResult.ok(ctx.id, ctx.nonce, result, signer.sign(ctx.nonce, result, resolvedUpstreamData?.id ?: ctx.upstream.getId()), resolvedUpstreamData, ctx, it.finalization)
|
||||
val source = if (resolvedUpstreamData.isNotEmpty()) {
|
||||
resolvedUpstreamData[0].id
|
||||
} else {
|
||||
ctx.upstream.getId()
|
||||
}
|
||||
CallResult.ok(ctx.id, ctx.nonce, result, signer.sign(ctx.nonce, result, source), resolvedUpstreamData, ctx, it.finalization)
|
||||
} else {
|
||||
CallResult.ok(ctx.id, null, result, null, resolvedUpstreamData, ctx, it.finalization)
|
||||
}
|
||||
@@ -446,8 +466,8 @@ open class NativeCall(
|
||||
.onErrorResume {
|
||||
Mono.just(CallResult.fail(ctx.id, ctx.nonce, it, ctx))
|
||||
}.doOnNext {
|
||||
if (it.finalization != null && it.upstreamSettingsData != null) {
|
||||
ctx.upstream.addFinalization(it.finalization, it.upstreamSettingsData.id)
|
||||
if (it.finalization != null && it.upstreamSettingsData.isNotEmpty()) {
|
||||
ctx.upstream.addFinalization(it.finalization, it.upstreamSettingsData[0].id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,7 +485,9 @@ open class NativeCall(
|
||||
return SpannedReader(reader, tracer, RPC_READER)
|
||||
.read(ctx.payload.toChainRequest(ctx.nonce, ctx.forwardedSelector, ctx.streamRequest))
|
||||
.map {
|
||||
val resolvedUpstreamData = it.resolvedUpstreamData ?: ctx.upstream.getUpstreamSettingsData()
|
||||
val resolvedUpstreamData = it.resolvedUpstreamData.ifEmpty {
|
||||
ctx.upstream.getUpstreamSettingsData()?.run { listOf(this) } ?: emptyList()
|
||||
}
|
||||
if (it.stream == null) {
|
||||
val bytes = ctx.resultDecorator.processResult(it)
|
||||
validateResult(bytes, "remote", ctx)
|
||||
@@ -563,8 +585,8 @@ open class NativeCall(
|
||||
}
|
||||
override fun processResult(result: RequestReader.Result): ByteArray {
|
||||
val bytes = result.value
|
||||
if (bytes.last() == quoteCode && result.resolvedUpstreamData != null) {
|
||||
val suffix = result.resolvedUpstreamData.nodeId
|
||||
if (bytes.last() == quoteCode && result.resolvedUpstreamData.isNotEmpty()) {
|
||||
val suffix = result.resolvedUpstreamData[0].nodeId
|
||||
.toUByte()
|
||||
.toString(16).padStart(2, padChar = '0').toByteArray()
|
||||
bytes[bytes.lastIndex] = suffix.first()
|
||||
@@ -678,7 +700,7 @@ open class NativeCall(
|
||||
val message: String,
|
||||
val upstreamError: ChainCallError?,
|
||||
val data: String?,
|
||||
val upstreamSettingsData: Upstream.UpstreamSettingsData? = null,
|
||||
val upstreamSettingsData: List<Upstream.UpstreamSettingsData> = emptyList(),
|
||||
) {
|
||||
|
||||
companion object {
|
||||
@@ -719,7 +741,7 @@ open class NativeCall(
|
||||
val result: ByteArray?,
|
||||
val error: CallError?,
|
||||
val signature: ResponseSigner.Signature?,
|
||||
val upstreamSettingsData: Upstream.UpstreamSettingsData?,
|
||||
val upstreamSettingsData: List<Upstream.UpstreamSettingsData>,
|
||||
val ctx: ValidCallContext<ParsedCallDetails>?,
|
||||
val stream: Flux<Chunk>? = null,
|
||||
val finalization: FinalizationData? = null,
|
||||
@@ -732,23 +754,23 @@ open class NativeCall(
|
||||
callError: CallError?,
|
||||
signature: ResponseSigner.Signature?,
|
||||
ctx: ValidCallContext<ParsedCallDetails>?,
|
||||
) : this(id, nonce, result, callError, signature, callError?.upstreamSettingsData, ctx)
|
||||
) : this(id, nonce, result, callError, signature, callError?.upstreamSettingsData ?: emptyList(), ctx)
|
||||
|
||||
companion object {
|
||||
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamSettingsData: Upstream.UpstreamSettingsData?, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
|
||||
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamSettingsData: List<Upstream.UpstreamSettingsData>, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
|
||||
return CallResult(id, nonce, result, null, signature, upstreamSettingsData, ctx)
|
||||
}
|
||||
|
||||
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamSettingsData: Upstream.UpstreamSettingsData?, ctx: ValidCallContext<ParsedCallDetails>?, final: FinalizationData?): CallResult {
|
||||
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamSettingsData: List<Upstream.UpstreamSettingsData>, ctx: ValidCallContext<ParsedCallDetails>?, final: FinalizationData?): CallResult {
|
||||
return CallResult(id, nonce, result, null, signature, upstreamSettingsData, ctx, null, final)
|
||||
}
|
||||
|
||||
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamSettingsData: Upstream.UpstreamSettingsData?, ctx: ValidCallContext<ParsedCallDetails>?, stream: Flux<Chunk>?): CallResult {
|
||||
fun ok(id: Int, nonce: Long?, result: ByteArray, signature: ResponseSigner.Signature?, upstreamSettingsData: List<Upstream.UpstreamSettingsData>, ctx: ValidCallContext<ParsedCallDetails>?, stream: Flux<Chunk>?): CallResult {
|
||||
return CallResult(id, nonce, result, null, signature, upstreamSettingsData, ctx, stream)
|
||||
}
|
||||
|
||||
fun fail(id: Int, nonce: Long?, error: CallError, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
|
||||
return CallResult(id, nonce, null, error, null, null, ctx)
|
||||
return CallResult(id, nonce, null, error, null, emptyList(), ctx)
|
||||
}
|
||||
|
||||
fun fail(id: Int, nonce: Long?, error: Throwable, ctx: ValidCallContext<ParsedCallDetails>?): CallResult {
|
||||
|
||||
@@ -36,7 +36,7 @@ data class ChainCallError(val code: Int, val message: String, val details: Any?)
|
||||
return ChainCallUpstreamException(id ?: ChainResponse.NumberId(-1), this)
|
||||
}
|
||||
|
||||
fun asException(id: ChainResponse.Id?, upstreamSettingsData: Upstream.UpstreamSettingsData?): ChainException {
|
||||
fun asException(id: ChainResponse.Id?, upstreamSettingsData: List<Upstream.UpstreamSettingsData>): ChainException {
|
||||
return ChainException(id ?: ChainResponse.NumberId(-1), this, upstreamSettingsData, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ package io.emeraldpay.dshackle.upstream
|
||||
class ChainCallUpstreamException(
|
||||
id: ChainResponse.Id,
|
||||
error: ChainCallError,
|
||||
) : ChainException(id, error, null, false)
|
||||
) : ChainException(id, error, emptyList(), false)
|
||||
|
||||
@@ -20,7 +20,7 @@ import io.emeraldpay.dshackle.upstream.ethereum.rpc.RpcException
|
||||
open class ChainException(
|
||||
val id: ChainResponse.Id,
|
||||
val error: ChainCallError,
|
||||
val upstreamSettingsData: Upstream.UpstreamSettingsData? = null,
|
||||
val upstreamSettingsData: List<Upstream.UpstreamSettingsData> = emptyList(),
|
||||
writableStackTrace: Boolean = true,
|
||||
cause: Throwable? = null,
|
||||
) : Exception(error.message, cause, true, writableStackTrace) {
|
||||
|
||||
@@ -33,18 +33,18 @@ class ChainResponse @JvmOverloads constructor(
|
||||
* 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 resolvedUpstreamData: Upstream.UpstreamSettingsData? = null,
|
||||
val resolvedUpstreamData: List<Upstream.UpstreamSettingsData> = emptyList(),
|
||||
val finalization: FinalizationData? = null,
|
||||
) {
|
||||
|
||||
constructor(stream: Flux<Chunk>, id: Int) :
|
||||
this(null, null, NumberId(id.toLong()), stream, null, null, null)
|
||||
this(null, null, NumberId(id.toLong()), stream, null, emptyList(), null)
|
||||
|
||||
constructor(result: ByteArray?, error: ChainCallError?) : this(result, error, NumberId(0), null, null)
|
||||
|
||||
constructor(result: ByteArray?, error: ChainCallError?, resolvedUpstreamData: Upstream.UpstreamSettingsData?) :
|
||||
constructor(result: ByteArray?, error: ChainCallError?, resolvedUpstreamData: List<Upstream.UpstreamSettingsData>) :
|
||||
this(result, error, NumberId(0), null, null, resolvedUpstreamData, null)
|
||||
constructor(result: ByteArray?, resolvedUpstreamData: Upstream.UpstreamSettingsData?, finalization: FinalizationData) :
|
||||
constructor(result: ByteArray?, resolvedUpstreamData: List<Upstream.UpstreamSettingsData>, finalization: FinalizationData) :
|
||||
this(result, null, NumberId(0), null, null, resolvedUpstreamData, finalization)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -157,7 +157,7 @@ open class EthereumCachingReader(
|
||||
) : Reader<K, Result<D>> {
|
||||
override fun read(key: K): Mono<Result<D>> {
|
||||
return reader.read(key)
|
||||
.map { Result(it, null) }
|
||||
.map { Result(it, emptyList()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +274,6 @@ class EthereumDirectReader(
|
||||
|
||||
data class Result<T>(
|
||||
val data: T,
|
||||
val resolvedUpstreamData: Upstream.UpstreamSettingsData?,
|
||||
val resolvedUpstreamData: List<Upstream.UpstreamSettingsData>,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class EthereumLocalReader(
|
||||
return commonRequests(key)?.switchIfEmpty {
|
||||
// we need to explicitly return null to prevent executeOnRemote
|
||||
// for example
|
||||
Mono.just(ChainResponse(nullValue, null, null))
|
||||
Mono.just(ChainResponse(nullValue, null, emptyList()))
|
||||
} ?: Mono.empty()
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ class EthereumLocalReader(
|
||||
}
|
||||
|
||||
return logsOracle.estimate(limit?.toLong(), fromBlock, toBlock, address, topics)
|
||||
.map { ChainResponse(it.toByteArray(), null, null) }
|
||||
.map { ChainResponse(it.toByteArray(), null, emptyList()) }
|
||||
}
|
||||
|
||||
private fun parseBlockRef(blockRef: String?): Long {
|
||||
|
||||
@@ -378,7 +378,7 @@ open class WsConnectionImpl(
|
||||
RpcResponseError.CODE_INTERNAL_ERROR,
|
||||
"Response not received from WebSocket",
|
||||
),
|
||||
null,
|
||||
emptyList(),
|
||||
false,
|
||||
)
|
||||
|
||||
|
||||
@@ -127,7 +127,16 @@ class JsonRpcGrpcClient(
|
||||
} else {
|
||||
null
|
||||
}
|
||||
Mono.just(ChainResponse(bytes, null, ChainResponse.NumberId(0), null, signature, Upstream.UpstreamSettingsData(0, resp.upstreamId, resp.upstreamNodeVersion)))
|
||||
Mono.just(
|
||||
ChainResponse(
|
||||
bytes,
|
||||
null,
|
||||
ChainResponse.NumberId(0),
|
||||
null,
|
||||
signature,
|
||||
listOf(Upstream.UpstreamSettingsData(0, resp.upstreamId, resp.upstreamNodeVersion)),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
metrics?.fails?.increment()
|
||||
Mono.error(
|
||||
|
||||
@@ -62,7 +62,7 @@ class BaseHandlerSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.items.add(request)
|
||||
call.ids[0] = 5
|
||||
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null, null)
|
||||
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, List.of(), null, null)
|
||||
when:
|
||||
def act = Flux.from(handler.execute(Chain.ETHEREUM__MAINNET, call, requestHandler, false))
|
||||
.collectList()
|
||||
@@ -85,7 +85,7 @@ class BaseHandlerSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.BATCH)
|
||||
call.items.add(request)
|
||||
call.ids[0] = 5
|
||||
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null, null)
|
||||
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, List.of(), null, null)
|
||||
when:
|
||||
def act = Flux.from(handler.execute(Chain.ETHEREUM__MAINNET, call, requestHandler, false))
|
||||
.collectList()
|
||||
@@ -116,8 +116,8 @@ class BaseHandlerSpec extends Specification {
|
||||
call.items.add(request2)
|
||||
call.ids[1] = 6
|
||||
def response = [
|
||||
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null, null, null),
|
||||
new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null, null)
|
||||
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, List.of(), null, null),
|
||||
new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, List.of(), null, null)
|
||||
]
|
||||
when:
|
||||
def act = Flux.from(handler.execute(Chain.ETHEREUM__MAINNET, call, requestHandler, true))
|
||||
@@ -149,8 +149,8 @@ class BaseHandlerSpec extends Specification {
|
||||
call.items.add(request2)
|
||||
call.ids[1] = 6
|
||||
def response = [
|
||||
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null, null, null),
|
||||
new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, null, null, null)
|
||||
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, List.of(), null, null),
|
||||
new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, List.of(), null, null)
|
||||
]
|
||||
when:
|
||||
def act = Flux.from(handler.execute(Chain.ETHEREUM__MAINNET, call, requestHandler, true))
|
||||
@@ -189,8 +189,8 @@ class BaseHandlerSpec extends Specification {
|
||||
|
||||
// note there is only 2 responses
|
||||
def response = [
|
||||
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, null, null, null),
|
||||
new NativeCall.CallResult(2, null, '{"foo": 3}'.bytes, null, null, null, null, null)
|
||||
new NativeCall.CallResult(1, null, '{"foo": 2}'.bytes, null, null, List.of(), null, null),
|
||||
new NativeCall.CallResult(2, null, '{"foo": 3}'.bytes, null, null, List.of(), null, null)
|
||||
]
|
||||
when:
|
||||
def act = Flux.from(handler.execute(Chain.ETHEREUM__MAINNET, call, requestHandler, true))
|
||||
|
||||
@@ -42,7 +42,7 @@ class HttpHandlerSpec extends Specification {
|
||||
.setMethod("test_test")
|
||||
.setPayload(ByteString.copyFromUtf8("[]"))
|
||||
.build()
|
||||
def respItem = new NativeCall.CallResult(1, null, "100".bytes, null, null, null, null, null)
|
||||
def respItem = new NativeCall.CallResult(1, null, "100".bytes, null, null, List.of(), null, null)
|
||||
def req = BlockchainOuterClass.NativeCallRequest.newBuilder()
|
||||
.setChain(Common.ChainRef.CHAIN_ETHEREUM__MAINNET)
|
||||
.addItems(reqItem)
|
||||
@@ -128,7 +128,7 @@ class HttpHandlerSpec extends Specification {
|
||||
def act = handler.execute(Chain.ETHEREUM__MAINNET, call, new AccessHandlerHttp.NoOpHandler(), false)
|
||||
|
||||
then:
|
||||
1 * nativeCall.nativeCallResult(_) >> Flux.just(new NativeCall.CallResult(1, null, "".bytes, null, null, null, null, null))
|
||||
1 * nativeCall.nativeCallResult(_) >> Flux.just(new NativeCall.CallResult(1, null, "".bytes, null, null, List.of(), null, null))
|
||||
StepVerifier.create(act)
|
||||
.expectNext("hello")
|
||||
.expectComplete()
|
||||
|
||||
@@ -86,7 +86,7 @@ class WebsocketHandlerSpec extends Specification {
|
||||
|
||||
def "Respond to a single call"() {
|
||||
setup:
|
||||
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, new Upstream.UpstreamSettingsData("test"), null, null)
|
||||
def response = new NativeCall.CallResult(0, null, '{"foo": 1}'.bytes, null, null, List.of(new Upstream.UpstreamSettingsData("test")), null, null)
|
||||
|
||||
def nativeCall = Mock(NativeCall) {
|
||||
1 * it.nativeCallResult(_) >> Flux.fromIterable([response])
|
||||
|
||||
@@ -85,7 +85,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = 105
|
||||
def data = [
|
||||
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null, null, null)
|
||||
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, List.of(), null, null)
|
||||
]
|
||||
when:
|
||||
def act = writer.toJson(call, data[0])
|
||||
@@ -98,7 +98,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = 1
|
||||
def data = [
|
||||
new NativeCall.CallResult(1, null, null, new NativeCall.CallError(1, "Internal Error", null, null, null), null, null, null, null)
|
||||
new NativeCall.CallResult(1, null, null, new NativeCall.CallError(1, "Internal Error", null, null, List.of()), null, List.of(), null, null)
|
||||
]
|
||||
when:
|
||||
def act = writer.toJson(call, data[0])
|
||||
@@ -111,7 +111,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = "aaa"
|
||||
def data = [
|
||||
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null, null, null)
|
||||
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, List.of(), null, null)
|
||||
]
|
||||
when:
|
||||
def act = writer.toJson(call, data[0])
|
||||
@@ -126,9 +126,9 @@ class WriteRpcJsonSpec extends Specification {
|
||||
call.ids[2] = 11
|
||||
call.ids[3] = 15
|
||||
def data = [
|
||||
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, null, null, null),
|
||||
new NativeCall.CallResult(2, null, null, new NativeCall.CallError(2, "oops", null, null, null), null, null, null, null),
|
||||
new NativeCall.CallResult(3, null, '{"hash": "0x2484f459dc"}'.bytes, null, null, null, null, null),
|
||||
new NativeCall.CallResult(1, null, '"0x98dbb1"'.bytes, null, null, List.of(), null, null),
|
||||
new NativeCall.CallResult(2, null, null, new NativeCall.CallError(2, "oops", null, null, List.of()), null, List.of(), null, null),
|
||||
new NativeCall.CallResult(3, null, '{"hash": "0x2484f459dc"}'.bytes, null, null, List.of(), null, null),
|
||||
]
|
||||
when:
|
||||
def act = Flux.fromIterable(data)
|
||||
@@ -154,7 +154,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = 10
|
||||
def data = [
|
||||
new NativeCall.CallResult(1, null, '"0x1"'.bytes, null, null, null, null, null),
|
||||
new NativeCall.CallResult(1, null, '"0x1"'.bytes, null, null, List.of(), null, null),
|
||||
]
|
||||
when:
|
||||
def act = Flux.fromIterable(data)
|
||||
|
||||
@@ -182,7 +182,7 @@ class BroadcastReaderSpec extends Specification {
|
||||
when:
|
||||
def act = reader
|
||||
.read(new ChainRequest("eth_sendRawTransaction", new ListParams(["0x1"])))
|
||||
.switchIfEmpty(Mono.just(new RequestReader.Result(new byte[0], null, 0, null, null)))
|
||||
.switchIfEmpty(Mono.just(new RequestReader.Result(new byte[0], null, 0, List.of(), null)))
|
||||
then:
|
||||
StepVerifier.create(act)
|
||||
.expectErrorMessage("Unhandled Upstream error")
|
||||
|
||||
@@ -123,7 +123,7 @@ class NativeCallSpec extends Specification {
|
||||
def nativeCall = nativeCall()
|
||||
nativeCall.requestReaderFactory = Mock(RequestReaderFactory) {
|
||||
1 * create(_) >> Mock(RequestReader) {
|
||||
1 * read(_) >> Mono.just(new RequestReader.Result("\"foo\"".bytes, null, 1, new Upstream.UpstreamSettingsData((byte)1, "test", "v"), null))
|
||||
1 * read(_) >> Mono.just(new RequestReader.Result("\"foo\"".bytes, null, 1, List.of(new Upstream.UpstreamSettingsData((byte)1, "test", "v")), null))
|
||||
}
|
||||
}
|
||||
def call = new NativeCall.ValidCallContext(1, 10, TestingCommons.multistream(TestingCommons.api()), new Selector.UpstreamFilter(Selector.empty), quorum,
|
||||
@@ -170,7 +170,7 @@ class NativeCallSpec extends Specification {
|
||||
nativeCall.requestReaderFactory = Mock(RequestReaderFactory) {
|
||||
1 * create(_) >> Mock(RequestReader) {
|
||||
1 * read(new ChainRequest("eth_test", new ListParams(), 10)) >> Mono.error(
|
||||
new ChainException(ChainResponse.Id.from(12), new ChainCallError(-32123, "Foo Bar", "Foo Bar Baz"), null, true, null)
|
||||
new ChainException(ChainResponse.Id.from(12), new ChainCallError(-32123, "Foo Bar", "Foo Bar Baz"), List.of(), true, null)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ class NativeCallSpec extends Specification {
|
||||
|
||||
when:
|
||||
def resp = nativeCall.buildResponse(
|
||||
new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, null, null, null, null)
|
||||
new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, null, List.of(), null, null)
|
||||
)
|
||||
then:
|
||||
resp.id == 1561
|
||||
@@ -246,7 +246,7 @@ class NativeCallSpec extends Specification {
|
||||
|
||||
when:
|
||||
def resp = nativeCall.buildResponse(
|
||||
new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, new ResponseSigner.Signature("sig1".bytes, "test", 100), new Upstream.UpstreamSettingsData("test"), null, null)
|
||||
new NativeCall.CallResult(1561, 10, objectMapper.writeValueAsBytes(json), null, new ResponseSigner.Signature("sig1".bytes, "test", 100), List.of(new Upstream.UpstreamSettingsData("test")), null, null)
|
||||
)
|
||||
then:
|
||||
resp.id == 1561
|
||||
@@ -609,7 +609,7 @@ class NativeCallSpec extends Specification {
|
||||
def nativeCall = nativeCall(multistreamHolder)
|
||||
nativeCall.requestReaderFactory = Mock(RequestReaderFactory) {
|
||||
1 * create(_) >> Mock(RequestReader) {
|
||||
1 * read(_) >> Mono.just(new RequestReader.Result("\"0xab\"".bytes, null, 1, new Upstream.UpstreamSettingsData((byte) 255, "", ""), null))
|
||||
1 * read(_) >> Mono.just(new RequestReader.Result("\"0xab\"".bytes, null, 1, List.of(new Upstream.UpstreamSettingsData((byte) 255, "", "")), null))
|
||||
}
|
||||
}
|
||||
def call = new NativeCall.ValidCallContext(1, 10, multistream, new Selector.UpstreamFilter(Selector.empty), quorum,
|
||||
@@ -642,7 +642,7 @@ class NativeCallSpec extends Specification {
|
||||
def nativeCall = nativeCall(multistreamHolder)
|
||||
nativeCall.requestReaderFactory = Mock(RequestReaderFactory) {
|
||||
1 * create(_) >> Mock(RequestReader) {
|
||||
1 * read(_) >> Mono.just(new RequestReader.Result("\"0xab\"".bytes, null, 1, new Upstream.UpstreamSettingsData((byte) 1, "", ""), null))
|
||||
1 * read(_) >> Mono.just(new RequestReader.Result("\"0xab\"".bytes, null, 1, List.of(new Upstream.UpstreamSettingsData((byte) 1, "", "")), null))
|
||||
}
|
||||
}
|
||||
def call = new NativeCall.ValidCallContext(1, 10, multistream, new Selector.UpstreamFilter(Selector.empty), quorum,
|
||||
|
||||
@@ -108,7 +108,7 @@ class ApiReaderMock implements Reader<ChainRequest, ChainResponse> {
|
||||
}
|
||||
error = new ChainCallError(-32601, "Method ${request.method} with ${request.params} is not mocked")
|
||||
}
|
||||
return new ChainResponse(result, error, ChainResponse.Id.from(request.id), null, null, null, null)
|
||||
return new ChainResponse(result, error, ChainResponse.Id.from(request.id), null, null, List.of(), null)
|
||||
} as Callable<ChainResponse>
|
||||
return Mono.fromCallable(call)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class EthereumDirectReaderSpec extends Specification {
|
||||
|
||||
String hash1 = "0x40d15edaff9acdabd2a1c96fd5f683b3300aad34e7015f34def3c56ba8a7ffb5"
|
||||
String address1 = "0xe0aadb0a012dbcdc529c4c743d3e0385a0b54d3d"
|
||||
Upstream.UpstreamSettingsData data = new Upstream.UpstreamSettingsData("test")
|
||||
List<Upstream.UpstreamSettingsData> data = List.of(new Upstream.UpstreamSettingsData("test"))
|
||||
def "Reads block by finalization"() {
|
||||
setup:
|
||||
def json = new BlockJson().tap {
|
||||
|
||||
@@ -73,7 +73,7 @@ class EthereumLocalReaderSpec extends Specification {
|
||||
_ * txByHashAsCont() >> new EmptyReader<>()
|
||||
1 * blocksByHeightAsCont() >> Mock(Reader) {
|
||||
1 * read(101L) >> Mono.just(
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(101L), null)
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(101L), List.of())
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ class EthereumLocalReaderSpec extends Specification {
|
||||
_ * txByHashAsCont() >> new EmptyReader<>()
|
||||
1 * blocksByHeightAsCont() >> Mock(Reader) {
|
||||
1 * read(0L) >> Mono.just(
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(0L), null)
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(0L), List.of())
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ class EthereumLocalReaderSpec extends Specification {
|
||||
_ * txByHashAsCont() >> new EmptyReader<>()
|
||||
1 * blocksByHeightAsCont() >> Mock(Reader) {
|
||||
1 * read(74735L) >> Mono.just(
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(74735L), null)
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(74735L), List.of())
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class EthereumLocalReaderSpec extends Specification {
|
||||
def reader = Mock(EthereumCachingReader) {
|
||||
1 * blockByFinalization() >> Mock(Reader) {
|
||||
1 * read(FinalizationType.SAFE_BLOCK) >> Mono.just(
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(74735L), null)
|
||||
new EthereumDirectReader.Result<>(TestingCommons.blockForEthereum(74735L), List.of())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package io.emeraldpay.dshackle.upstream.ethereum.subscribe
|
||||
|
||||
import io.emeraldpay.dshackle.Chain
|
||||
import io.emeraldpay.dshackle.data.BlockId
|
||||
import io.emeraldpay.dshackle.data.TxId
|
||||
import io.emeraldpay.dshackle.reader.Reader
|
||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumDirectReader
|
||||
import io.emeraldpay.dshackle.upstream.ethereum.domain.Address
|
||||
@@ -47,7 +46,7 @@ class ProduceLogsSpec extends Specification {
|
||||
setup:
|
||||
def logs = Mock(Reader) {
|
||||
1 * it.read(BlockId.from("0x668b92d6b8c7db1350fd527fec4885ce5be2159b2b7daf6b126babdcbaa349da")) >>
|
||||
Mono.just(new EthereumDirectReader.Result<>([], null))
|
||||
Mono.just(new EthereumDirectReader.Result<>([], List.of()))
|
||||
}
|
||||
def producer = new ProduceLogs(logs, Chain.ETHEREUM__MAINNET)
|
||||
def update = new ConnectBlockUpdates.Update(
|
||||
@@ -69,7 +68,7 @@ class ProduceLogsSpec extends Specification {
|
||||
|
||||
def logs = Mock(Reader) {
|
||||
1 * it.read(BlockId.from("0x668b92d6b8c7db1350fd527fec4885ce5be2159b2b7daf6b126babdcbaa349da")) >>
|
||||
Mono.just(new EthereumDirectReader.Result<>(logs, null))
|
||||
Mono.just(new EthereumDirectReader.Result<>(logs, List.of()))
|
||||
}
|
||||
def producer = new ProduceLogs(logs, Chain.ETHEREUM__MAINNET)
|
||||
def update = new ConnectBlockUpdates.Update(
|
||||
@@ -92,7 +91,7 @@ class ProduceLogsSpec extends Specification {
|
||||
setup:
|
||||
def logs = Mock(Reader) {
|
||||
1 * it.read(BlockId.from("0x668b92d6b8c7db1350fd527fec4885ce5be2159b2b7daf6b126babdcbaa349da")) >>
|
||||
Mono.just(new EthereumDirectReader.Result<>(logs, null))
|
||||
Mono.just(new EthereumDirectReader.Result<>(logs, List.of()))
|
||||
}
|
||||
def producer = new ProduceLogs(logs, Chain.ETHEREUM__MAINNET)
|
||||
def update1 = new ConnectBlockUpdates.Update(
|
||||
|
||||
@@ -65,7 +65,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize int id and null result"() {
|
||||
setup:
|
||||
def json = new ChainResponse("null".bytes, null, new ChainResponse.NumberId(1), null, null, null)
|
||||
def json = new ChainResponse("null".bytes, null, new ChainResponse.NumberId(1), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -74,7 +74,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize int id and string result"() {
|
||||
setup:
|
||||
def json = new ChainResponse('"Hello World"'.bytes, null, new ChainResponse.NumberId(10), null, null, null)
|
||||
def json = new ChainResponse('"Hello World"'.bytes, null, new ChainResponse.NumberId(10), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -83,7 +83,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize int id and object result"() {
|
||||
setup:
|
||||
def json = new ChainResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new ChainResponse.NumberId(101), null, null, null)
|
||||
def json = new ChainResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new ChainResponse.NumberId(101), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -92,7 +92,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize int id and error"() {
|
||||
setup:
|
||||
def json = new ChainResponse(null, new ChainCallError(-32041, "Oooops"), new ChainResponse.NumberId(101), null, null, null)
|
||||
def json = new ChainResponse(null, new ChainCallError(-32041, "Oooops"), new ChainResponse.NumberId(101), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -101,7 +101,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize string id and null result"() {
|
||||
setup:
|
||||
def json = new ChainResponse("null".bytes, null, new ChainResponse.StringId("asf01t1gg"), null, null, null)
|
||||
def json = new ChainResponse("null".bytes, null, new ChainResponse.StringId("asf01t1gg"), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -110,7 +110,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize string id and string result"() {
|
||||
setup:
|
||||
def json = new ChainResponse('"Hello World"'.bytes, null, new ChainResponse.StringId("10"), null, null, null)
|
||||
def json = new ChainResponse('"Hello World"'.bytes, null, new ChainResponse.StringId("10"), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -119,7 +119,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize string id and object result"() {
|
||||
setup:
|
||||
def json = new ChainResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new ChainResponse.StringId("g8gk19g"), null, null, null)
|
||||
def json = new ChainResponse('{"foo": "Hello World", "bar": 1}'.bytes, null, new ChainResponse.StringId("g8gk19g"), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -130,7 +130,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
setup:
|
||||
def json = new ChainResponse(null,
|
||||
new ChainCallError(-32041, "Oooops"),
|
||||
new ChainResponse.StringId("9kbo29gkaasf"), null, null, null )
|
||||
new ChainResponse.StringId("9kbo29gkaasf"), null, null, List.of())
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
|
||||
@@ -33,7 +33,7 @@ class NativeCallTest {
|
||||
),
|
||||
) {
|
||||
on { nativeCallResult(request) } doReturn Flux.just(
|
||||
NativeCall.CallResult.ok(1, null, "0x1".toByteArray(), null, Upstream.UpstreamSettingsData("id"), null),
|
||||
NativeCall.CallResult.ok(1, null, "0x1".toByteArray(), null, listOf(Upstream.UpstreamSettingsData("id")), null),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class NativeCallTest {
|
||||
),
|
||||
) {
|
||||
on { nativeCallResult(request) } doReturn Flux.just(
|
||||
NativeCall.CallResult(1, null, null, NativeCall.CallError(50001, "message", null, null, Upstream.UpstreamSettingsData("upId")), null, null),
|
||||
NativeCall.CallResult(1, null, null, NativeCall.CallError(50001, "message", null, null, listOf(Upstream.UpstreamSettingsData("upId"))), null, null),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ class NativeCallTest {
|
||||
),
|
||||
) {
|
||||
on { nativeCallResult(request) } doReturn Flux.just(
|
||||
NativeCall.CallResult.ok(1, null, "".toByteArray(), null, Upstream.UpstreamSettingsData("upId"), null, chunks),
|
||||
NativeCall.CallResult.ok(1, null, "".toByteArray(), null, listOf(Upstream.UpstreamSettingsData("upId")), null, chunks),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user