problem: routes calls to upstreams that quorum wouldnt accept anyway (not-lagging quorum to lagging upstreams)
solution: select only possible acceptable upstreams before the call
This commit is contained in:
@@ -23,6 +23,11 @@ import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
/**
|
||||
* Accepts a response only from a "synced" upstreams, where "maxLag" specifies how many blocks it may be behind to be considered as "synced"
|
||||
*
|
||||
* NOTE: NativeCall checks the quorums and applies a HeightSelector if NotLaggingQuorum is enabled for a call
|
||||
*/
|
||||
class NotLaggingQuorum(val maxLag: Long = 0): CallQuorum {
|
||||
|
||||
private val result: AtomicReference<ByteArray> = AtomicReference()
|
||||
|
||||
@@ -24,6 +24,7 @@ import io.emeraldpay.dshackle.SilentException
|
||||
import io.emeraldpay.dshackle.upstream.*
|
||||
import io.emeraldpay.dshackle.quorum.AlwaysQuorum
|
||||
import io.emeraldpay.dshackle.quorum.CallQuorum
|
||||
import io.emeraldpay.dshackle.quorum.NotLaggingQuorum
|
||||
import io.emeraldpay.dshackle.quorum.QuorumReaderFactory
|
||||
import io.emeraldpay.dshackle.upstream.calls.EthereumCallSelector
|
||||
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
|
||||
@@ -151,12 +152,19 @@ open class NativeCall(
|
||||
.withMatcher(csm)
|
||||
.forMethod(method)
|
||||
.forLabels(Selector.convertToMatcher(request.selector))
|
||||
.build()
|
||||
|
||||
val callQuorum = upstream.getMethods().getQuorumFor(method) ?: AlwaysQuorum()
|
||||
callQuorum.init(upstream.getHead())
|
||||
|
||||
CallContext(it.id, upstream, matcher, callQuorum, RawCallDetails(method, params))
|
||||
// for NotLaggingQuorum it makes sense to select compatible upstreams before the call
|
||||
if (callQuorum is NotLaggingQuorum) {
|
||||
val lag = callQuorum.maxLag
|
||||
val minHeight = ((upstream.getHead().getCurrentHeight() ?: 0) - lag).coerceAtLeast(0)
|
||||
val heightMatcher = Selector.HeightMatcher(minHeight)
|
||||
matcher.withMatcher(heightMatcher)
|
||||
}
|
||||
|
||||
CallContext(it.id, upstream, matcher.build(), callQuorum, RawCallDetails(method, params))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,10 @@ class Selector {
|
||||
return matchers.all { it.matches(up) }
|
||||
}
|
||||
|
||||
fun getMatchers(): Collection<Matcher> {
|
||||
return Collections.unmodifiableCollection(matchers)
|
||||
}
|
||||
|
||||
fun <T : Matcher> getMatcher(type: Class<T>): T? {
|
||||
return matchers.find { type.isAssignableFrom(it.javaClass) } as T?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user