solution: refactor upstreams to make them blockchain specific

This commit is contained in:
Igor Artamonov
2020-04-11 22:55:47 -04:00
parent 0ae9d8ec3c
commit 0ab68ea782
49 changed files with 600 additions and 314 deletions

View File

@@ -0,0 +1,22 @@
package io.emeraldpay.dshackle
import io.emeraldpay.grpc.Chain
import spock.lang.Specification
class BlockchainTypeSpec extends Specification {
def "Correct type for ethereum"() {
expect:
BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM
where:
chain << [Chain.ETHEREUM, Chain.ETHEREUM_CLASSIC, Chain.TESTNET_KOVAN, Chain.TESTNET_MORDEN]
}
def "Correct type for bitcoin"() {
expect:
BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN
where:
chain << [Chain.BITCOIN, Chain.TESTNET_BITCOIN]
}
}

View File

@@ -22,6 +22,7 @@ import io.emeraldpay.dshackle.test.EthereumUpstreamMock
import io.emeraldpay.dshackle.test.UpstreamsMock
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.grpc.Chain
import io.infinitape.etherjar.domain.BlockHash
import io.infinitape.etherjar.domain.TransactionId
@@ -38,7 +39,7 @@ class StreamHeadSpec extends Specification {
def "Errors on unavailable chain"() {
setup:
def upstreams = new UpstreamsMock(Chain.ETHEREUM, Stub(Upstream))
def upstreams = new UpstreamsMock(Chain.ETHEREUM, Stub(EthereumUpstream))
def streamHead = new StreamHead(upstreams)
when:
def flux = streamHead.add(

View File

@@ -33,7 +33,7 @@ import spock.lang.Specification
import java.time.Duration
class TrackAddressSpec extends Specification {
class TrackEthereumAddressSpec extends Specification {
def chain = Common.ChainRef.CHAIN_ETHEREUM
def address1 = "0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f"
@@ -59,7 +59,7 @@ class TrackAddressSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackAddress trackAddress = new TrackAddress(upstreams, Schedulers.immediate())
TrackEthereumAddress trackAddress = new TrackEthereumAddress(upstreams, Schedulers.immediate())
trackAddress.init()
apiMock.answer("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
@@ -101,7 +101,7 @@ class TrackAddressSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackAddress trackAddress = new TrackAddress(upstreams, Schedulers.immediate())
TrackEthereumAddress trackAddress = new TrackEthereumAddress(upstreams, Schedulers.immediate())
trackAddress.init()
apiMock.answerOnce("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")

View File

@@ -36,7 +36,7 @@ import spock.lang.Specification
import java.time.Duration
import java.time.Instant
class TrackTxSpec extends Specification {
class TrackEthereumTxSpec extends Specification {
def chain = Common.ChainRef.CHAIN_ETHEREUM
def txId = "0xba61ce4672751fd6086a9ac2b55547a5555af17535b6c0334ede2ecb6d64070a"
@@ -45,8 +45,8 @@ class TrackTxSpec extends Specification {
def "Gives details for an old transaction"() {
setup:
def req = BlockchainOuterClass.TxStatusRequest.newBuilder()
.setChain(chain)
.setConfirmationLimit(6)
.setChain(chain)
.setConfirmationLimit(6)
.setTxId(txId)
.build()
@@ -91,7 +91,7 @@ class TrackTxSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams, Schedulers.immediate())
trackTx.init()
apiMock.answer("eth_getTransactionByHash", [txId], txJson)
@@ -123,7 +123,7 @@ class TrackTxSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams, Schedulers.immediate())
trackTx.init()
apiMock.answer("eth_getTransactionByHash", [txId], null)
@@ -180,7 +180,7 @@ class TrackTxSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams, Schedulers.immediate())
trackTx.init()
apiMock.answerOnce("eth_getTransactionByHash", [txId], null)
@@ -279,7 +279,7 @@ class TrackTxSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams, Schedulers.immediate())
trackTx.init()
apiMock.answerOnce("eth_getTransactionByHash", [txId], null)
@@ -320,7 +320,7 @@ class TrackTxSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams, Schedulers.immediate())
trackTx.init()
def req = BlockchainOuterClass.TxStatusRequest.newBuilder()
@@ -341,7 +341,7 @@ class TrackTxSpec extends Specification {
def apiMock = TestingCommons.api(Stub(ReactorRpcClient))
def upstreamMock = TestingCommons.upstream(apiMock)
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
TrackEthereumTx trackTx = new TrackEthereumTx(upstreams, Schedulers.immediate())
trackTx.init()
def req = BlockchainOuterClass.TxStatusRequest.newBuilder()

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.test
import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.upstream.calls.CallMethods
import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
@@ -33,11 +33,11 @@ class EthereumUpstreamMock extends EthereumUpstream {
EthereumHeadMock ethereumHeadMock = new EthereumHeadMock()
EthereumUpstreamMock(@NotNull Chain chain, @NotNull DirectEthereumApi api) {
this(chain, api, new QuorumBasedMethods(TestingCommons.objectMapper(), chain))
this(chain, api, new DefaultEthereumMethods(TestingCommons.objectMapper(), chain))
}
EthereumUpstreamMock(@NotNull String id, @NotNull Chain chain, @NotNull DirectEthereumApi api) {
this(id, chain, api, new QuorumBasedMethods(TestingCommons.objectMapper(), chain))
this(id, chain, api, new DefaultEthereumMethods(TestingCommons.objectMapper(), chain))
}
EthereumUpstreamMock(@NotNull Chain chain, @NotNull DirectEthereumApi api, CallMethods methods) {

View File

@@ -27,6 +27,7 @@ import io.emeraldpay.dshackle.upstream.AggregatedUpstream
import io.emeraldpay.dshackle.upstream.ChainUpstreams
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstreams
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.grpc.Chain
import io.infinitape.etherjar.rpc.JacksonRpcConverter
@@ -75,7 +76,7 @@ class TestingCommons {
}
static AggregatedUpstream aggregatedUpstream(EthereumUpstream up) {
return new ChainUpstreams(Chain.ETHEREUM, [up], Caches.default(), objectMapper())
return new EthereumChainUpstreams(Chain.ETHEREUM, [up], Caches.default(), objectMapper())
}
static CachesFactory emptyCaches() {

View File

@@ -18,16 +18,17 @@ package io.emeraldpay.dshackle.test
import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
import io.emeraldpay.dshackle.upstream.ChainUpstreams
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.Upstream
import io.emeraldpay.dshackle.upstream.Upstreams
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstreams
import io.emeraldpay.grpc.Chain
import org.jetbrains.annotations.NotNull
import reactor.core.publisher.Flux
class UpstreamsMock implements Upstreams {
private Map<Chain, QuorumBasedMethods> target = [:]
private Map<Chain, DefaultEthereumMethods> target = [:]
private Map<Chain, AggregatedUpstream> upstreams = [:]
UpstreamsMock(Chain chain, Upstream up) {
@@ -40,7 +41,7 @@ class UpstreamsMock implements Upstreams {
AggregatedUpstream addUpstream(@NotNull Chain chain, @NotNull Upstream up) {
if (!upstreams.containsKey(chain)) {
upstreams[chain] = new ChainUpstreams(chain, [up], Caches.default(), TestingCommons.objectMapper())
upstreams[chain] = new EthereumChainUpstreams(chain, [up], Caches.default(), TestingCommons.objectMapper())
} else {
upstreams[chain].addUpstream(up)
}
@@ -63,9 +64,9 @@ class UpstreamsMock implements Upstreams {
}
@Override
QuorumBasedMethods getDefaultMethods(@NotNull Chain chain) {
DefaultEthereumMethods getDefaultMethods(@NotNull Chain chain) {
if (target[chain] == null) {
QuorumBasedMethods targets = new QuorumBasedMethods(TestingCommons.objectMapper(), chain)
DefaultEthereumMethods targets = new DefaultEthereumMethods(TestingCommons.objectMapper(), chain)
target[chain] = targets
}
return target[chain]

View File

@@ -21,6 +21,7 @@ import io.emeraldpay.dshackle.test.EthereumUpstreamMock
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.calls.DirectCallMethods
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
import io.emeraldpay.dshackle.upstream.ethereum.EthereumChainUpstreams
import io.emeraldpay.grpc.Chain
import spock.lang.Specification
@@ -30,7 +31,7 @@ class AggregatedUpstreamSpec extends Specification {
setup:
def up1 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, Stub(DirectEthereumApi), new DirectCallMethods(["eth_test1", "eth_test2"]))
def up2 = new EthereumUpstreamMock("test1", Chain.ETHEREUM, Stub(DirectEthereumApi), new DirectCallMethods(["eth_test2", "eth_test3"]))
def aggr = new ChainUpstreams(Chain.ETHEREUM, [up1, up2], Caches.default(), TestingCommons.objectMapper())
def aggr = new EthereumChainUpstreams(Chain.ETHEREUM, [up1, up2], Caches.default(), TestingCommons.objectMapper())
when:
aggr.onUpstreamsUpdated()
def act = aggr.getMethods()

View File

@@ -19,7 +19,7 @@ import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.startup.QuorumForLabels
import io.emeraldpay.dshackle.test.EthereumApiStub
import io.emeraldpay.dshackle.test.TestingCommons
import io.emeraldpay.dshackle.upstream.calls.QuorumBasedMethods
import io.emeraldpay.dshackle.upstream.calls.DefaultEthereumMethods
import io.emeraldpay.dshackle.upstream.ethereum.DirectEthereumApi
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumWs
@@ -35,7 +35,7 @@ class FilteredApisSpec extends Specification {
def rpcClient = Stub(ReactorRpcClient)
def objectMapper = TestingCommons.objectMapper()
def ethereumTargets = new QuorumBasedMethods(objectMapper, Chain.ETHEREUM)
def ethereumTargets = new DefaultEthereumMethods(objectMapper, Chain.ETHEREUM)
def "Verifies labels"() {
setup:

View File

@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.emeraldpay.dshackle.upstream
package io.emeraldpay.dshackle.upstream.ethereum
import io.emeraldpay.dshackle.upstream.ethereum.EthereumHead
import io.emeraldpay.dshackle.upstream.HeadLagObserver
import io.emeraldpay.dshackle.upstream.Upstream
import io.infinitape.etherjar.rpc.json.BlockJson
import reactor.core.publisher.Flux
import reactor.core.publisher.TopicProcessor
@@ -25,7 +26,7 @@ import spock.lang.Specification
import java.time.Duration
class HeadLagObserverSpec extends Specification {
class EthereumHeadLagObserverSpec extends Specification {
def "Updates lag distance"() {
setup:
@@ -64,7 +65,7 @@ class HeadLagObserverSpec extends Specification {
1 * up2.setLag(1)
1 * up2.setLag(0)
HeadLagObserver observer = new HeadLagObserver(master, [up1, up2])
HeadLagObserver observer = new EthereumHeadLagObserver(master, [up1, up2])
when:
def act = observer.subscription().take(Duration.ofMillis(1200))
@@ -78,7 +79,7 @@ class HeadLagObserverSpec extends Specification {
def "Probes until there is no difference"() {
setup:
EthereumHead master = Mock()
HeadLagObserver observer = new HeadLagObserver(master, [])
HeadLagObserver observer = new EthereumHeadLagObserver(master, [])
Upstream up = Mock()
def blocks = [100, 101, 102].collect { i ->
@@ -103,7 +104,7 @@ class HeadLagObserverSpec extends Specification {
def "Correct distance"() {
setup:
EthereumHead master = Mock()
HeadLagObserver observer = new HeadLagObserver(master, [])
HeadLagObserver observer = new EthereumHeadLagObserver(master, [])
expect:
def top = new BlockJson().with {
it.number = topHeight

View File

@@ -34,7 +34,7 @@ import spock.lang.Specification
import java.time.Duration
import java.util.concurrent.CompletableFuture
class GrpcUpstreamSpec extends Specification {
class EthereumGrpcUpstreamSpec extends Specification {
MockServer mockServer = new MockServer()
ObjectMapper objectMapper = TestingCommons.objectMapper()
@@ -70,7 +70,7 @@ class GrpcUpstreamSpec extends Specification {
}
})
def transport = ReactorEmeraldClient.newBuilder().connectUsing(client.channel).build()
def upstream = new GrpcUpstream("test", chain, client, objectMapper, transport)
def upstream = new EthereumGrpcUpstream("test", chain, client, objectMapper, transport)
upstream.setLag(0)
upstream.init(BlockchainOuterClass.DescribeChain.newBuilder()
.addAllSupportedMethods(["eth_getBlockByHash"])
@@ -126,7 +126,7 @@ class GrpcUpstreamSpec extends Specification {
}
})
def transport = ReactorEmeraldClient.newBuilder().connectUsing(client.channel).build()
def upstream = new GrpcUpstream("test", Chain.ETHEREUM, client, objectMapper, transport)
def upstream = new EthereumGrpcUpstream("test", Chain.ETHEREUM, client, objectMapper, transport)
upstream.setLag(0)
upstream.init(BlockchainOuterClass.DescribeChain.newBuilder()
.addAllSupportedMethods(["eth_getBlockByHash"])
@@ -186,7 +186,7 @@ class GrpcUpstreamSpec extends Specification {
}
})
def transport = ReactorEmeraldClient.newBuilder().connectUsing(client.channel).build()
def upstream = new GrpcUpstream("test", chain, client, objectMapper, transport)
def upstream = new EthereumGrpcUpstream("test", chain, client, objectMapper, transport)
upstream.setLag(0)
upstream.init(BlockchainOuterClass.DescribeChain.newBuilder()
.addAllSupportedMethods(["eth_getBlockByHash"])