solution: add support for Polygon/Matic

This commit is contained in:
Chase Wright
2021-08-11 22:25:33 -05:00
committed by GitHub
parent 7cf86129f0
commit 802d1c8eb8
16 changed files with 42 additions and 115 deletions

View File

@@ -61,7 +61,7 @@ configurations {
}
dependencies {
implementation "io.emeraldpay:emerald-api:0.9.2"
implementation "io.emeraldpay:emerald-api:0.9.4"
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"

View File

@@ -10,22 +10,27 @@ enum ChainRef {
CHAIN_UNSPECIFIED = 0;
CHAIN_BITCOIN = 1;
CHAIN_GRIN = 2;
// CHAIN_GRIN = 2;
CHAIN_ETHEREUM = 100;
CHAIN_ETHEREUM_CLASSIC = 101;
CHAIN_FANTOM = 102; // Fantom, https://fantom.foundation/
// Sidechains and state channels
CHAIN_LIGHTNING = 1001;
// Sidechains and state channels start with 1_000
// CHAIN_LIGHTNING = 1001;
CHAIN_MATIC = 1002; // Matic PoS Ethereum sidechain based on Polygon
CHAIN_RSK = 1003; // RSK sidechain, https://www.rsk.co/
// Testnets
// Testnets start with 10_000
CHAIN_MORDEN = 10001;
CHAIN_KOVAN = 10002;
CHAIN_TESTNET_BITCOIN = 10003;
CHAIN_FLOONET = 10004;
// CHAIN_FLOONET = 10004;
CHAIN_GOERLI = 10005;
CHAIN_ROPSTEN = 10006;
CHAIN_RINKEBY = 10007;
// Non-standard starts from 50000
// Non-standard starts from 20_000
}
message SingleAddress {

View File

@@ -1,48 +0,0 @@
/**
* Copyright (c) 2020 EmeraldPay, Inc
* Copyright (c) 2020 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
import io.emeraldpay.grpc.Chain
/**
* Type of the blockchain, architecture-wise
*/
enum class BlockchainType {
ETHEREUM,
BITCOIN,
OTHER;
companion object {
@JvmStatic
fun fromBlockchain(blockchain: Chain): BlockchainType {
if (blockchain == Chain.ETHEREUM
|| blockchain == Chain.ETHEREUM_CLASSIC
|| blockchain == Chain.TESTNET_KOVAN
|| blockchain == Chain.TESTNET_ROPSTEN
|| blockchain == Chain.TESTNET_RINKEBY
|| blockchain == Chain.TESTNET_MORDEN
|| blockchain == Chain.TESTNET_GOERLI) {
return ETHEREUM
}
if (blockchain == Chain.BITCOIN || blockchain == Chain.TESTNET_BITCOIN) {
return BITCOIN
}
return OTHER
}
}
}

View File

@@ -15,7 +15,7 @@
*/
package io.emeraldpay.dshackle.config
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import io.infinitape.etherjar.domain.Address
@@ -41,7 +41,7 @@ class TokensConfig(
type == null -> type
address.isNullOrBlank() -> "address"
blockchain != null
&& BlockchainType.fromBlockchain(blockchain!!) == BlockchainType.ETHEREUM
&& BlockchainType.from(blockchain!!) == BlockchainType.ETHEREUM
&& !Address.isValidAddress(address) -> "address"
else -> null
}

View File

@@ -19,7 +19,6 @@ package io.emeraldpay.dshackle.rpc
import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.grpc.Chain

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.upstream.Capability
@@ -53,7 +53,7 @@ class TrackBitcoinAddress(
override fun isSupported(chain: Chain, asset: String): Boolean {
return (asset == "bitcoin" || asset == "btc" || asset == "satoshi")
&& BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN && multistreamHolder.isAvailable(chain)
&& BlockchainType.from(chain) == BlockchainType.BITCOIN && multistreamHolder.isAvailable(chain)
}
/**

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.rpc
import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.bitcoin.BitcoinMultistream
@@ -45,7 +45,7 @@ class TrackBitcoinTx(
}
override fun isSupported(chain: Chain): Boolean {
return BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN && multistreamHolder.isAvailable(chain)
return BlockchainType.from(chain) == BlockchainType.BITCOIN && multistreamHolder.isAvailable(chain)
}
override fun subscribe(request: BlockchainOuterClass.TxStatusRequest): Flux<BlockchainOuterClass.TxStatus> {

View File

@@ -2,7 +2,7 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.config.TokensConfig
import io.emeraldpay.dshackle.upstream.Head
@@ -54,7 +54,7 @@ class TrackERC20Address(
override fun isSupported(chain: Chain, asset: String): Boolean {
return tokens.containsKey(TokenId(chain, asset.toLowerCase())) &&
BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
BlockchainType.from(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
}
override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.rpc
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.upstream.MultistreamHolder
@@ -42,7 +42,7 @@ class TrackEthereumAddress(
override fun isSupported(chain: Chain, asset: String): Boolean {
return asset == "ether" &&
BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
BlockchainType.from(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
}
override fun getBalance(request: BlockchainOuterClass.BalanceRequest): Flux<BlockchainOuterClass.AddressBalance> {

View File

@@ -19,7 +19,7 @@ package io.emeraldpay.dshackle.rpc
import com.google.protobuf.ByteString
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.SilentException
import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.data.TxId
@@ -63,7 +63,7 @@ class TrackEthereumTx(
private val log = LoggerFactory.getLogger(TrackEthereumTx::class.java)
override fun isSupported(chain: Chain): Boolean {
return BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
return BlockchainType.from(chain) == BlockchainType.ETHEREUM && multistreamHolder.isAvailable(chain)
}
override fun subscribe(request: BlockchainOuterClass.TxStatusRequest): Flux<BlockchainOuterClass.TxStatus> {

View File

@@ -16,7 +16,7 @@
*/
package io.emeraldpay.dshackle.startup
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.cache.CachesFactory
import io.emeraldpay.dshackle.config.UpstreamsConfig
@@ -62,6 +62,8 @@ open class ConfiguredUpstreams(
"ethereum" to Chain.ETHEREUM,
"ethereum-classic" to Chain.ETHEREUM_CLASSIC,
"eth" to Chain.ETHEREUM,
"polygon" to Chain.MATIC,
"matic" to Chain.MATIC,
"etc" to Chain.ETHEREUM_CLASSIC,
"morden" to Chain.TESTNET_MORDEN,
"kovan" to Chain.TESTNET_KOVAN,
@@ -93,7 +95,7 @@ open class ConfiguredUpstreams(
}
val options = (up.options ?: UpstreamsConfig.Options())
.merge(defaultOptions[chain] ?: UpstreamsConfig.Options.getDefaults())
when (BlockchainType.fromBlockchain(chain)) {
when (BlockchainType.from(chain)) {
BlockchainType.ETHEREUM -> {
buildEthereumUpstream(up.cast(UpstreamsConfig.EthereumConnection::class.java), chain, options)
}

View File

@@ -16,7 +16,7 @@
*/
package io.emeraldpay.dshackle.upstream
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.cache.CachesEnabled
import io.emeraldpay.dshackle.cache.CachesFactory
import io.emeraldpay.dshackle.startup.UpstreamChange
@@ -58,7 +58,7 @@ open class CurrentMultistreamHolder(
log.debug("Upstream update: ${change.type} ${change.chain} via ${change.upstream.getId()}")
val chain = change.chain
try {
when (BlockchainType.fromBlockchain(chain)) {
when (BlockchainType.from(chain)) {
BlockchainType.ETHEREUM -> {
val up = change.upstream.cast(EthereumUpstream::class.java)
val current = chainMapping[chain] as Multistream?
@@ -138,7 +138,7 @@ open class CurrentMultistreamHolder(
}
fun setupDefaultMethods(chain: Chain): CallMethods {
val created = when (BlockchainType.fromBlockchain(chain)) {
val created = when (BlockchainType.from(chain)) {
BlockchainType.ETHEREUM -> DefaultEthereumMethods(chain)
BlockchainType.BITCOIN -> DefaultBitcoinMethods()
else -> throw IllegalStateException("Unsupported chain: $chain")

View File

@@ -119,6 +119,9 @@ class DefaultEthereumMethods(
Chain.ETHEREUM_CLASSIC == chain -> {
"\"1\""
}
Chain.MATIC == chain -> {
"\"137\""
}
Chain.TESTNET_MORDEN == chain -> {
"\"2\""
}
@@ -142,6 +145,9 @@ class DefaultEthereumMethods(
Chain.ETHEREUM == chain -> {
"\"0x1\""
}
Chain.MATIC == chain -> {
"\"0x89\""
}
Chain.TESTNET_ROPSTEN == chain -> {
"\"0x3\""
}

View File

@@ -18,7 +18,7 @@ package io.emeraldpay.dshackle.upstream.grpc
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.ReactorBlockchainGrpc
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.dshackle.Defaults
import io.emeraldpay.dshackle.FileResolver
import io.emeraldpay.dshackle.config.AuthConfig
@@ -179,7 +179,7 @@ class GrpcUpstreams(
.register(Metrics.globalRegistry)
)
val blockchainType = BlockchainType.fromBlockchain(chain)
val blockchainType = BlockchainType.from(chain)
if (blockchainType == BlockchainType.ETHEREUM) {
return getOrCreateEthereum(chain, metrics)
} else if (blockchainType == BlockchainType.BITCOIN) {

View File

@@ -1,37 +0,0 @@
/**
* 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
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_GOERLI, Chain.TESTNET_MORDEN, Chain.TESTNET_RINKEBY, Chain.TESTNET_ROPSTEN]
}
def "Correct type for bitcoin"() {
expect:
BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN
where:
chain << [Chain.BITCOIN, Chain.TESTNET_BITCOIN]
}
}

View File

@@ -17,7 +17,6 @@
package io.emeraldpay.dshackle.test
import io.emeraldpay.dshackle.BlockchainType
import io.emeraldpay.dshackle.cache.Caches
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.Multistream
@@ -30,6 +29,7 @@ import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.ethereum.EthereumMultistream
import io.emeraldpay.dshackle.upstream.ethereum.EthereumReader
import io.emeraldpay.dshackle.upstream.ethereum.EthereumUpstream
import io.emeraldpay.grpc.BlockchainType
import io.emeraldpay.grpc.Chain
import org.jetbrains.annotations.NotNull
import reactor.core.publisher.Flux
@@ -45,7 +45,7 @@ class MultistreamHolderMock implements MultistreamHolder {
Multistream addUpstream(@NotNull Chain chain, @NotNull Upstream up) {
if (!upstreams.containsKey(chain)) {
if (BlockchainType.fromBlockchain(chain) == BlockchainType.ETHEREUM) {
if (BlockchainType.from(chain) == BlockchainType.ETHEREUM) {
if (up instanceof EthereumMultistream) {
upstreams[chain] = up
} else if (up instanceof EthereumUpstream) {
@@ -54,7 +54,7 @@ class MultistreamHolderMock implements MultistreamHolder {
throw new IllegalArgumentException("Unsupported upstream type ${up.class}")
}
upstreams[chain].start()
} else if (BlockchainType.fromBlockchain(chain) == BlockchainType.BITCOIN) {
} else if (BlockchainType.from(chain) == BlockchainType.BITCOIN) {
if (up instanceof BitcoinMultistream) {
upstreams[chain] = up
} else if (up instanceof BitcoinRpcUpstream) {