diff --git a/src/main/kotlin/io/emeraldpay/dshackle/quorum/NonceQuorum.kt b/src/main/kotlin/io/emeraldpay/dshackle/quorum/NonceQuorum.kt deleted file mode 100644 index b74c8905..00000000 --- a/src/main/kotlin/io/emeraldpay/dshackle/quorum/NonceQuorum.kt +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (c) 2020 EmeraldPay, Inc - * Copyright (c) 2019 ETCDEV GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.emeraldpay.dshackle.quorum - -import io.emeraldpay.dshackle.upstream.Head -import io.emeraldpay.dshackle.upstream.Upstream -import io.emeraldpay.dshackle.upstream.signature.ResponseSigner -import io.emeraldpay.etherjar.hex.HexQuantity -import java.util.concurrent.locks.ReentrantLock -import kotlin.concurrent.withLock - -open class NonceQuorum( - val tries: Int = 3 -) : CallQuorum, ValueAwareQuorum(String::class.java) { - - private val lock = ReentrantLock() - private var resultValue = 0L - private var result: ByteArray? = null - private var receivedTimes = 0 - private var errors = 0 - private var sig: ResponseSigner.Signature? = null - private var providedUpstreamId: String? = null - - override fun init(head: Head) { - } - - override fun isResolved(): Boolean { - lock.withLock { - return receivedTimes >= tries && !isFailed() - } - } - - override fun isFailed(): Boolean { - return errors >= tries - } - override fun getSignature(): ResponseSigner.Signature? { - return sig - } - - 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 -> - HexQuantity.from(str).value.toLong() - } - lock.withLock { - receivedTimes++ - if (value != null && value > resultValue) { - resultValue = value - result = response - sig = signature - this.providedUpstreamId = providedUpstreamId - } else if (result == null) { - result = response - sig = signature - this.providedUpstreamId = providedUpstreamId - } - } - } - - override fun getResult(): ByteArray? { - return result - } - - override fun recordError( - response: ByteArray?, - errorMessage: String?, - signature: ResponseSigner.Signature?, - upstream: Upstream, - providedUpstreamId: String? - ) { - errors++ - } - - override fun toString(): String { - return "Quorum: Confirm with $tries upstreams" - } -} diff --git a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt index 9a92a528..53308d90 100644 --- a/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt +++ b/src/main/kotlin/io/emeraldpay/dshackle/upstream/calls/DefaultEthereumMethods.kt @@ -21,7 +21,6 @@ import io.emeraldpay.dshackle.Global import io.emeraldpay.dshackle.quorum.AlwaysQuorum import io.emeraldpay.dshackle.quorum.BroadcastQuorum import io.emeraldpay.dshackle.quorum.CallQuorum -import io.emeraldpay.dshackle.quorum.NonceQuorum import io.emeraldpay.dshackle.quorum.NotLaggingQuorum import io.emeraldpay.dshackle.quorum.NotNullQuorum import io.emeraldpay.etherjar.rpc.RpcException @@ -149,7 +148,7 @@ class DefaultEthereumMethods( possibleNotIndexedMethods.contains(method) -> NotNullQuorum() specialMethods.contains(method) -> { when (method) { - "eth_getTransactionCount" -> NonceQuorum() + "eth_getTransactionCount" -> NotLaggingQuorum(0) "eth_getBalance" -> NotLaggingQuorum(0) "eth_sendRawTransaction" -> BroadcastQuorum() "eth_blockNumber" -> NotLaggingQuorum(0) diff --git a/src/test/groovy/io/emeraldpay/dshackle/quorum/NonceQuorumSpec.groovy b/src/test/groovy/io/emeraldpay/dshackle/quorum/NonceQuorumSpec.groovy deleted file mode 100644 index 1962ece0..00000000 --- a/src/test/groovy/io/emeraldpay/dshackle/quorum/NonceQuorumSpec.groovy +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (c) 2019 ETCDEV GmbH - * Copyright (c) 2020 EmeraldPay, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.emeraldpay.dshackle.quorum - -import com.fasterxml.jackson.databind.ObjectMapper -import io.emeraldpay.dshackle.Global -import io.emeraldpay.dshackle.upstream.Head -import io.emeraldpay.dshackle.upstream.Upstream -import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException -import spock.lang.Specification - -class NonceQuorumSpec extends Specification { - - ObjectMapper objectMapper = Global.objectMapper - - def "Gets max value"() { - setup: - def q = Spy(new NonceQuorum(3)) - def upstream1 = Stub(Upstream) - def upstream2 = Stub(Upstream) - def upstream3 = Stub(Upstream) - - when: - q.init(Stub(Head)) - then: - !q.isResolved() - - when: - q.record('"0x10"'.bytes, null, upstream1, null) - then: - !q.isResolved() - 1 * q.recordValue(_, "0x10", _, _, _) - - when: - q.record('"0x11"'.bytes, null, upstream2, null) - then: - !q.isResolved() - 1 * q.recordValue(_, "0x11", _, _, _) - - when: - q.record('"0x10"'.bytes, null, upstream3, null) - then: - 1 * q.recordValue(_, "0x10", _, _, _) - q.isResolved() - objectMapper.readValue(q.result, Object) == "0x11" - } - - def "Ignores errors"() { - setup: - def q = Spy(new NonceQuorum(3)) - def upstream1 = Stub(Upstream) - def upstream2 = Stub(Upstream) - def upstream3 = Stub(Upstream) - - when: - q.init(Stub(Head)) - then: - !q.isResolved() - - when: - q.record(new JsonRpcException(1, "Internal"), null, upstream1) - then: - !q.isResolved() - 1 * q.recordError(_, _, _, _, _) - - when: - q.record('"0x11"'.bytes, null, upstream2, null) - then: - !q.isResolved() - 1 * q.recordValue(_, "0x11", _, _, _) - - when: - q.record('"0x10"'.bytes, null, upstream3, null) - then: - 1 * q.recordValue(_, "0x10", _, _, _) - !q.isResolved() - - when: - q.record('"0x11"'.bytes, null, upstream1, null) - then: - 1 * q.recordValue(_, "0x11", _, _, _) - q.isResolved() - objectMapper.readValue(q.result, Object) == "0x11" - } - - def "Fail if too many errors"() { - setup: - def q = Spy(new NonceQuorum(3)) - def upstream1 = Stub(Upstream) - def upstream2 = Stub(Upstream) - def upstream3 = Stub(Upstream) - - when: - q.init(Stub(Head)) - then: - !q.isResolved() - !q.isFailed() - - when: - q.record(new JsonRpcException(1, "Internal"), null, upstream1) - then: - !q.isResolved() - !q.isFailed() - - when: - q.record(new JsonRpcException(1, "Internal"), null, upstream2) - then: - !q.isResolved() - !q.isFailed() - - when: - q.record(new JsonRpcException(1, "Internal"), null, upstream3) - then: - q.isFailed() - !q.isResolved() - q.getError() != null - q.getError().message == "Internal" - q.signature == null - } -}