added fantom, gnosis and avalanche networks
added retries for initial upstream validation
This commit is contained in:
@@ -151,6 +151,12 @@ Currently, dshackle supports next chains (should be used as chain names in confi
|
|||||||
- base-goerli
|
- base-goerli
|
||||||
- linea
|
- linea
|
||||||
- linea-goerli
|
- linea-goerli
|
||||||
|
- fantom
|
||||||
|
- fantom-testnet
|
||||||
|
- gnosis
|
||||||
|
- gnosis-chiado
|
||||||
|
- avalanche
|
||||||
|
- avalanche-fuji
|
||||||
|
|
||||||
=== Roles and Fallback upstream
|
=== Roles and Fallback upstream
|
||||||
|
|
||||||
|
|||||||
Submodule emerald-grpc updated: 1afdf11bbf...3a5a63d618
@@ -4,46 +4,21 @@ enum class BlockchainType {
|
|||||||
BITCOIN, EVM_POW, EVM_POS;
|
BITCOIN, EVM_POW, EVM_POS;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
val pow = setOf(
|
||||||
|
Chain.ETHEREUM_CLASSIC__MAINNET, Chain.RSK__MAINNET, Chain.ETHEREUM__KOVAN,
|
||||||
|
Chain.ETHEREUM__MORDEN, Chain.ETHEREUM__RINKEBY
|
||||||
|
)
|
||||||
|
val bitcoin = setOf(Chain.BITCOIN__MAINNET, Chain.BITCOIN__TESTNET)
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun from(chain: Chain): BlockchainType {
|
fun from(chain: Chain): BlockchainType {
|
||||||
if (chain == Chain.ETHEREUM__ROPSTEN ||
|
return if (pow.contains(chain)) {
|
||||||
chain == Chain.POLYGON_POS__MAINNET ||
|
EVM_POW
|
||||||
chain == Chain.OPTIMISM__MAINNET ||
|
} else if (bitcoin.contains(chain)) {
|
||||||
chain == Chain.ARBITRUM__MAINNET ||
|
BITCOIN
|
||||||
chain == Chain.BSC__MAINNET ||
|
} else {
|
||||||
chain == Chain.ETHEREUM__GOERLI ||
|
EVM_POS
|
||||||
chain == Chain.ETHEREUM__MAINNET ||
|
|
||||||
chain == Chain.ETHEREUM__SEPOLIA ||
|
|
||||||
chain == Chain.ARBITRUM__GOERLI ||
|
|
||||||
chain == Chain.OPTIMISM__GOERLI ||
|
|
||||||
chain == Chain.ARBITRUM_NOVA__MAINNET ||
|
|
||||||
chain == Chain.POLYGON_ZKEVM__MAINNET ||
|
|
||||||
chain == Chain.POLYGON_ZKEVM__TESTNET ||
|
|
||||||
chain == Chain.ZKSYNC__MAINNET ||
|
|
||||||
chain == Chain.ZKSYNC__TESTNET ||
|
|
||||||
chain == Chain.POLYGON_POS__MUMBAI ||
|
|
||||||
chain == Chain.BASE__MAINNET ||
|
|
||||||
chain == Chain.BASE__GOERLI ||
|
|
||||||
chain == Chain.LINEA__MAINNET ||
|
|
||||||
chain == Chain.LINEA__GOERLI
|
|
||||||
) {
|
|
||||||
return EVM_POS
|
|
||||||
}
|
}
|
||||||
if (chain == Chain.ETHEREUM_CLASSIC__MAINNET ||
|
|
||||||
chain == Chain.FANTOM__MAINNET ||
|
|
||||||
chain == Chain.RSK__MAINNET ||
|
|
||||||
chain == Chain.ETHEREUM__KOVAN ||
|
|
||||||
chain == Chain.ETHEREUM__MORDEN ||
|
|
||||||
chain == Chain.ETHEREUM__RINKEBY
|
|
||||||
) {
|
|
||||||
return EVM_POW
|
|
||||||
}
|
|
||||||
if (chain == Chain.BITCOIN__MAINNET ||
|
|
||||||
chain == Chain.BITCOIN__TESTNET
|
|
||||||
) {
|
|
||||||
return BITCOIN
|
|
||||||
}
|
|
||||||
throw IllegalArgumentException("Unknown type of blockchain: $chain")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ enum class Chain(val id: Int, val chainCode: String, val chainName: String) {
|
|||||||
ZKSYNC__MAINNET(1009, "ZKSYNC", "ZkSync Era"),
|
ZKSYNC__MAINNET(1009, "ZKSYNC", "ZkSync Era"),
|
||||||
BASE__MAINNET(1010, "BASE", "Base"),
|
BASE__MAINNET(1010, "BASE", "Base"),
|
||||||
LINEA__MAINNET(1011, "LINEA", "Linea"),
|
LINEA__MAINNET(1011, "LINEA", "Linea"),
|
||||||
|
GNOSIS__MAINNET(1012, "GNOSIS", "Gnosis"),
|
||||||
|
AVALANCHE__MAINNET(1013, "AVALANCHE", "Avalanche"),
|
||||||
|
|
||||||
// Testnets
|
// Testnets
|
||||||
ETHEREUM__MORDEN(10001, "MORDEN", "Morden Testnet"),
|
ETHEREUM__MORDEN(10001, "MORDEN", "Morden Testnet"),
|
||||||
@@ -88,7 +90,10 @@ enum class Chain(val id: Int, val chainCode: String, val chainName: String) {
|
|||||||
"Polygon POS Mumbai Testnet"
|
"Polygon POS Mumbai Testnet"
|
||||||
),
|
),
|
||||||
BASE__GOERLI(10014, "BASE_GOERLI", "Base Goerli Testnet"),
|
BASE__GOERLI(10014, "BASE_GOERLI", "Base Goerli Testnet"),
|
||||||
LINEA__GOERLI(10015, "LINEA_GOERLI", "Linea Goerli Testnet");
|
LINEA__GOERLI(10015, "LINEA_GOERLI", "Linea Goerli Testnet"),
|
||||||
|
FANTOM__TESTNET(10016, "FANTOM_TESTNET", "Fantom Testnet"),
|
||||||
|
GNOSIS__CHIADO(10017, "GNOSIS_CHIADO", "Gnosis Chiado Testnet"),
|
||||||
|
AVALANCHE__FUJI(10018, "AVALANCHE_FUJI", "Avalanche Fuji Testnet");
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun byId(id: Int): Chain {
|
fun byId(id: Int): Chain {
|
||||||
|
|||||||
@@ -81,6 +81,12 @@ class Global {
|
|||||||
"base-goerli" to Chain.BASE__GOERLI,
|
"base-goerli" to Chain.BASE__GOERLI,
|
||||||
"linea" to Chain.LINEA__MAINNET,
|
"linea" to Chain.LINEA__MAINNET,
|
||||||
"linea-goerli" to Chain.LINEA__GOERLI,
|
"linea-goerli" to Chain.LINEA__GOERLI,
|
||||||
|
"fantom" to Chain.FANTOM__MAINNET,
|
||||||
|
"fantom-testnet" to Chain.FANTOM__TESTNET,
|
||||||
|
"gnosis" to Chain.GNOSIS__MAINNET,
|
||||||
|
"gnosis-chiado" to Chain.GNOSIS__CHIADO,
|
||||||
|
"avalanche" to Chain.AVALANCHE__MAINNET,
|
||||||
|
"avalanche-fuji" to Chain.AVALANCHE__FUJI,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun chainById(id: String?): Chain {
|
fun chainById(id: String?): Chain {
|
||||||
|
|||||||
@@ -104,6 +104,15 @@ class DefaultEthereumMethods(
|
|||||||
|
|
||||||
Chain.LINEA__MAINNET to HardcodedData("\"59144\"", "\"0xe708\""),
|
Chain.LINEA__MAINNET to HardcodedData("\"59144\"", "\"0xe708\""),
|
||||||
Chain.LINEA__GOERLI to HardcodedData("\"59140\"", "\"0xe704\""),
|
Chain.LINEA__GOERLI to HardcodedData("\"59140\"", "\"0xe704\""),
|
||||||
|
|
||||||
|
Chain.FANTOM__MAINNET to HardcodedData("\"250\"", "\"0xfa\""),
|
||||||
|
Chain.FANTOM__TESTNET to HardcodedData("\"4002\"", "\"0xfa2\""),
|
||||||
|
|
||||||
|
Chain.GNOSIS__MAINNET to HardcodedData("\"100\"", "\"0x64\""),
|
||||||
|
Chain.GNOSIS__CHIADO to HardcodedData("\"10200\"", "\"0x27d8\""),
|
||||||
|
|
||||||
|
Chain.AVALANCHE__MAINNET to HardcodedData("\"43114\"", "\"0xa86a\""),
|
||||||
|
Chain.AVALANCHE__FUJI to HardcodedData("\"43113\"", "\"0xa869\""),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getChainByData(data: HardcodedData) = CHAIN_DATA.entries.find { it.value == data }?.key
|
fun getChainByData(data: HardcodedData) = CHAIN_DATA.entries.find { it.value == data }?.key
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import org.springframework.scheduling.concurrent.CustomizableThreadFactory
|
|||||||
import reactor.core.publisher.Flux
|
import reactor.core.publisher.Flux
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import reactor.core.scheduler.Schedulers
|
import reactor.core.scheduler.Schedulers
|
||||||
|
import reactor.kotlin.extra.retry.retryRandomBackoff
|
||||||
import reactor.util.function.Tuple2
|
import reactor.util.function.Tuple2
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
@@ -93,6 +94,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor(
|
|||||||
UpstreamAvailability.OK
|
UpstreamAvailability.OK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.doOnError { err -> log.error("Error during syncing validation for ${upstream.getId()}", err) }
|
||||||
.onErrorReturn(UpstreamAvailability.UNAVAILABLE)
|
.onErrorReturn(UpstreamAvailability.UNAVAILABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ open class EthereumUpstreamValidator @JvmOverloads constructor(
|
|||||||
UpstreamAvailability.OK
|
UpstreamAvailability.OK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.doOnError { err -> log.error("Error during peer count validation for ${upstream.getId()}", err) }
|
||||||
.onErrorReturn(UpstreamAvailability.UNAVAILABLE)
|
.onErrorReturn(UpstreamAvailability.UNAVAILABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,13 +206,25 @@ open class EthereumUpstreamValidator @JvmOverloads constructor(
|
|||||||
Mono.fromCallable { log.error("No response for eth_call limit check from ${upstream.getId()}") }
|
Mono.fromCallable { log.error("No response for eth_call limit check from ${upstream.getId()}") }
|
||||||
.then(Mono.error(TimeoutException("Validation timeout for call limit")))
|
.then(Mono.error(TimeoutException("Validation timeout for call limit")))
|
||||||
)
|
)
|
||||||
|
.retryRandomBackoff(3, Duration.ofMillis(100), Duration.ofMillis(500)) { ctx ->
|
||||||
|
log.warn(
|
||||||
|
"error during validateCallLimit for ${upstream.getId()}, iteration ${ctx.iteration()}",
|
||||||
|
ctx.exception()
|
||||||
|
)
|
||||||
|
}
|
||||||
.onErrorReturn(false)
|
.onErrorReturn(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chainId(): Mono<String> {
|
private fun chainId(): Mono<String> {
|
||||||
return upstream.getIngressReader()
|
return upstream.getIngressReader()
|
||||||
.read(JsonRpcRequest("eth_chainId", emptyList()))
|
.read(JsonRpcRequest("eth_chainId", emptyList()))
|
||||||
.doOnError { log.error("Error during execution 'eth_chainId' - ${it.message}") }
|
.retryRandomBackoff(3, Duration.ofMillis(100), Duration.ofMillis(500)) { ctx ->
|
||||||
|
log.warn(
|
||||||
|
"error during chainId retrieving for ${upstream.getId()}, iteration ${ctx.iteration()}",
|
||||||
|
ctx.exception()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.doOnError { log.error("Error during execution 'eth_chainId' - ${it.message} for ${upstream.getId()}") }
|
||||||
.flatMap(JsonRpcResponse::requireResult)
|
.flatMap(JsonRpcResponse::requireResult)
|
||||||
.map { String(it) }
|
.map { String(it) }
|
||||||
}
|
}
|
||||||
@@ -217,7 +232,13 @@ open class EthereumUpstreamValidator @JvmOverloads constructor(
|
|||||||
private fun netVersion(): Mono<String> {
|
private fun netVersion(): Mono<String> {
|
||||||
return upstream.getIngressReader()
|
return upstream.getIngressReader()
|
||||||
.read(JsonRpcRequest("net_version", emptyList()))
|
.read(JsonRpcRequest("net_version", emptyList()))
|
||||||
.doOnError { log.error("Error during execution 'net_version' - ${it.message}") }
|
.retryRandomBackoff(3, Duration.ofMillis(100), Duration.ofMillis(500)) { ctx ->
|
||||||
|
log.warn(
|
||||||
|
"error during netVersion retrieving for ${upstream.getId()}, iteration ${ctx.iteration()}",
|
||||||
|
ctx.exception()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.doOnError { log.error("Error during execution 'net_version' - ${it.message} for ${upstream.getId()}") }
|
||||||
.flatMap(JsonRpcResponse::requireResult)
|
.flatMap(JsonRpcResponse::requireResult)
|
||||||
.map { String(it) }
|
.map { String(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,3 +90,41 @@ chain-settings:
|
|||||||
lags:
|
lags:
|
||||||
syncing: 40
|
syncing: 40
|
||||||
lagging: 20
|
lagging: 20
|
||||||
|
- id: avalanche
|
||||||
|
options:
|
||||||
|
validate-peers: false
|
||||||
|
validate-syncing: false
|
||||||
|
lags:
|
||||||
|
syncing: 10
|
||||||
|
lagging: 5
|
||||||
|
- id: avalanche-fuji
|
||||||
|
options:
|
||||||
|
validate-peers: false
|
||||||
|
validate-syncing: false
|
||||||
|
lags:
|
||||||
|
syncing: 10
|
||||||
|
lagging: 5
|
||||||
|
- id: gnosis
|
||||||
|
options:
|
||||||
|
validate-peers: false
|
||||||
|
lags:
|
||||||
|
syncing: 10
|
||||||
|
lagging: 5
|
||||||
|
- id: gnosis-chiado
|
||||||
|
options:
|
||||||
|
validate-peers: false
|
||||||
|
lags:
|
||||||
|
syncing: 10
|
||||||
|
lagging: 5
|
||||||
|
- id: fantom
|
||||||
|
options:
|
||||||
|
validate-peers: false
|
||||||
|
lags:
|
||||||
|
syncing: 10
|
||||||
|
lagging: 5
|
||||||
|
- id: fantom-testnet
|
||||||
|
options:
|
||||||
|
validate-peers: false
|
||||||
|
lags:
|
||||||
|
syncing: 10
|
||||||
|
lagging: 5
|
||||||
|
|||||||
Reference in New Issue
Block a user