check chain_ids on all networks (#507)
* check chain_ids on all networks
This commit is contained in:
@@ -115,7 +115,8 @@ class ChainsConfigReader(
|
|||||||
?: throw IllegalArgumentException("undefined code for $blockchain")
|
?: throw IllegalArgumentException("undefined code for $blockchain")
|
||||||
val grpcId = getValueAsInt(node, "grpcId")
|
val grpcId = getValueAsInt(node, "grpcId")
|
||||||
?: throw IllegalArgumentException("undefined code for $blockchain")
|
?: throw IllegalArgumentException("undefined code for $blockchain")
|
||||||
val netVersion = getValueAsLong(node, "net-version")?.toBigInteger() ?: BigInteger(chainId.drop(2), 16)
|
val netVersion = getValueAsLong(node, "net-version")?.toBigInteger() ?:
|
||||||
|
if (chainId.startsWith("0x")) BigInteger(chainId.drop(2), 16) else BigInteger.ZERO
|
||||||
val shortNames = getListOfString(node, "short-names")
|
val shortNames = getListOfString(node, "short-names")
|
||||||
?: throw IllegalArgumentException("undefined shortnames for $blockchain")
|
?: throw IllegalArgumentException("undefined shortnames for $blockchain")
|
||||||
val type = getValueAsString(node, "type")
|
val type = getValueAsString(node, "type")
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ chain-settings:
|
|||||||
settings:
|
settings:
|
||||||
expected-block-time: 12s
|
expected-block-time: 12s
|
||||||
mev-critical: true
|
mev-critical: true
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 6
|
syncing: 6
|
||||||
lagging: 1
|
lagging: 1
|
||||||
@@ -76,6 +77,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 3s
|
expected-block-time: 3s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -101,6 +103,7 @@ chain-settings:
|
|||||||
settings:
|
settings:
|
||||||
mev-critical: true
|
mev-critical: true
|
||||||
expected-block-time: 2.7s
|
expected-block-time: 2.7s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 20
|
syncing: 20
|
||||||
lagging: 10
|
lagging: 10
|
||||||
@@ -131,6 +134,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 260ms
|
expected-block-time: 260ms
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -155,6 +159,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 2s
|
expected-block-time: 2s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -179,6 +184,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 3s
|
expected-block-time: 3s
|
||||||
|
allow-pruning-requirement: true
|
||||||
mev-critical: true
|
mev-critical: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 20
|
syncing: 20
|
||||||
@@ -206,6 +212,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 2.7s
|
expected-block-time: 2.7s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
disable-validation: true
|
disable-validation: true
|
||||||
lags:
|
lags:
|
||||||
@@ -232,6 +239,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 260ms
|
expected-block-time: 260ms
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
disable-validation: true
|
disable-validation: true
|
||||||
lags:
|
lags:
|
||||||
@@ -249,6 +257,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 5s
|
expected-block-time: 5s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 70
|
syncing: 70
|
||||||
lagging: 50
|
lagging: 50
|
||||||
@@ -273,6 +282,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 2s
|
expected-block-time: 2s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -297,6 +307,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 12s
|
expected-block-time: 12s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 6
|
syncing: 6
|
||||||
lagging: 1
|
lagging: 1
|
||||||
@@ -319,6 +330,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 6s
|
expected-block-time: 6s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -343,6 +355,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 2s
|
expected-block-time: 2s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
validate-syncing: false
|
validate-syncing: false
|
||||||
@@ -392,6 +405,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 500ms
|
expected-block-time: 500ms
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -416,6 +430,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 1s
|
expected-block-time: 1s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -442,6 +457,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 5s
|
expected-block-time: 5s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 10
|
syncing: 10
|
||||||
lagging: 5
|
lagging: 5
|
||||||
@@ -464,6 +480,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 12s
|
expected-block-time: 12s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 6
|
syncing: 6
|
||||||
lagging: 1
|
lagging: 1
|
||||||
@@ -486,6 +503,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 12s
|
expected-block-time: 12s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 6
|
syncing: 6
|
||||||
lagging: 1
|
lagging: 1
|
||||||
@@ -554,6 +572,7 @@ chain-settings:
|
|||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
expected-block-time: 30s
|
expected-block-time: 30s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 40
|
syncing: 40
|
||||||
lagging: 20
|
lagging: 20
|
||||||
@@ -600,6 +619,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 6s
|
expected-block-time: 6s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -613,8 +633,7 @@ chain-settings:
|
|||||||
short-names: [kava]
|
short-names: [kava]
|
||||||
chain-id: 0x8ae
|
chain-id: 0x8ae
|
||||||
grpcId: 1025
|
grpcId: 1025
|
||||||
gas-price-condition:
|
gas-price-condition: eq 1000000000
|
||||||
- eq 1000000000
|
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
priority: 10
|
priority: 10
|
||||||
code: KAVA_TESTNET
|
code: KAVA_TESTNET
|
||||||
@@ -683,13 +702,13 @@ chain-settings:
|
|||||||
priority: 1
|
priority: 1
|
||||||
code: VARA_MAINNET
|
code: VARA_MAINNET
|
||||||
short-names: [vara]
|
short-names: [vara]
|
||||||
chain-id: 0x0
|
chain-id: Vara Network
|
||||||
grpcId: 1027
|
grpcId: 1027
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
priority: 1
|
priority: 1
|
||||||
code: VARA_TESTMET
|
code: VARA_TESTMET
|
||||||
short-names: [vara-testnet]
|
short-names: [vara-testnet]
|
||||||
chain-id: 0x0
|
chain-id: Vara Network Testnet
|
||||||
grpcId: 10036
|
grpcId: 10036
|
||||||
- id: solana
|
- id: solana
|
||||||
label: Solana
|
label: Solana
|
||||||
@@ -773,6 +792,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 5s
|
expected-block-time: 5s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 20
|
syncing: 20
|
||||||
lagging: 10
|
lagging: 10
|
||||||
@@ -835,6 +855,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 10s
|
expected-block-time: 10s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 10
|
syncing: 10
|
||||||
lagging: 5
|
lagging: 5
|
||||||
@@ -933,6 +954,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 2s
|
expected-block-time: 2s
|
||||||
|
allow-pruning-requirement: true
|
||||||
options:
|
options:
|
||||||
validate-peers: false
|
validate-peers: false
|
||||||
lags:
|
lags:
|
||||||
@@ -1022,6 +1044,7 @@ chain-settings:
|
|||||||
type: eth
|
type: eth
|
||||||
settings:
|
settings:
|
||||||
expected-block-time: 2s
|
expected-block-time: 2s
|
||||||
|
allow-pruning-requirement: true
|
||||||
lags:
|
lags:
|
||||||
syncing: 40
|
syncing: 40
|
||||||
lagging: 20
|
lagging: 20
|
||||||
@@ -1282,19 +1305,19 @@ chain-settings:
|
|||||||
code: NEAR_MAINNET
|
code: NEAR_MAINNET
|
||||||
grpcId: 1050
|
grpcId: 1050
|
||||||
short-names: [near]
|
short-names: [near]
|
||||||
chain-id: 0x0
|
chain-id: mainnet
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
priority: 5
|
priority: 5
|
||||||
code: NEAR_TESTNET
|
code: NEAR_TESTNET
|
||||||
grpcId: 10064
|
grpcId: 10064
|
||||||
short-names: [near-testnet]
|
short-names: [near-testnet]
|
||||||
chain-id: 0x0
|
chain-id: testnet
|
||||||
- id: Betanet
|
- id: Betanet
|
||||||
priority: 1
|
priority: 1
|
||||||
code: NEAR_BETANET
|
code: NEAR_BETANET
|
||||||
grpcId: 10065
|
grpcId: 10065
|
||||||
short-names: [near-betanet]
|
short-names: [near-betanet]
|
||||||
chain-id: 0x0
|
chain-id: betanet
|
||||||
- id: opcelestia-raspberry
|
- id: opcelestia-raspberry
|
||||||
label: OP Celestia Raspberry
|
label: OP Celestia Raspberry
|
||||||
type: eth
|
type: eth
|
||||||
@@ -1420,13 +1443,13 @@ chain-settings:
|
|||||||
lagging: 1
|
lagging: 1
|
||||||
chains:
|
chains:
|
||||||
- id: Mainnet
|
- id: Mainnet
|
||||||
chain-id: 0x0
|
chain-id: cosmoshub-4
|
||||||
short-names: [ cosmos-hub ]
|
short-names: [ cosmos-hub ]
|
||||||
code: COSMOS_HUB
|
code: COSMOS_HUB
|
||||||
grpcId: 1057
|
grpcId: 1057
|
||||||
priority: 100
|
priority: 100
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
chain-id: 0x0
|
chain-id: provider
|
||||||
short-names: [ cosmos-hub-testnet ]
|
short-names: [ cosmos-hub-testnet ]
|
||||||
code: COSMOS_HUB_TESTNET
|
code: COSMOS_HUB_TESTNET
|
||||||
grpcId: 10079
|
grpcId: 10079
|
||||||
@@ -1441,13 +1464,13 @@ chain-settings:
|
|||||||
lagging: 1
|
lagging: 1
|
||||||
chains:
|
chains:
|
||||||
- id: Mainnet
|
- id: Mainnet
|
||||||
chain-id: 0x0
|
chain-id: axelar-dojo-1
|
||||||
short-names: [ axelar ]
|
short-names: [ axelar ]
|
||||||
code: AXELAR
|
code: AXELAR
|
||||||
grpcId: 1059
|
grpcId: 1059
|
||||||
priority: 100
|
priority: 100
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
chain-id: 0x0
|
chain-id: axelar-testnet-lisbon-3
|
||||||
short-names: [ axelar-testnet ]
|
short-names: [ axelar-testnet ]
|
||||||
code: AXELAR_TESTNET
|
code: AXELAR_TESTNET
|
||||||
grpcId: 10081
|
grpcId: 10081
|
||||||
@@ -1462,13 +1485,13 @@ chain-settings:
|
|||||||
lagging: 1
|
lagging: 1
|
||||||
chains:
|
chains:
|
||||||
- id: Mainnet
|
- id: Mainnet
|
||||||
chain-id: 0x0
|
chain-id: osmosis
|
||||||
short-names: [ osmosis ]
|
short-names: [ osmosis ]
|
||||||
code: OSMOSIS
|
code: OSMOSIS
|
||||||
grpcId: 1060
|
grpcId: 1060
|
||||||
priority: 100
|
priority: 100
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
chain-id: 0x0
|
chain-id: osmo-test-5
|
||||||
short-names: [ osmosis-testnet ]
|
short-names: [ osmosis-testnet ]
|
||||||
code: OSMOSIS_TESTNET
|
code: OSMOSIS_TESTNET
|
||||||
grpcId: 10082
|
grpcId: 10082
|
||||||
@@ -1483,13 +1506,13 @@ chain-settings:
|
|||||||
lagging: 1
|
lagging: 1
|
||||||
chains:
|
chains:
|
||||||
- id: Mainnet
|
- id: Mainnet
|
||||||
chain-id: 0x0
|
chain-id: neutron-1
|
||||||
short-names: [ neutron ]
|
short-names: [ neutron ]
|
||||||
code: NEUTRON
|
code: NEUTRON
|
||||||
grpcId: 1061
|
grpcId: 1061
|
||||||
priority: 100
|
priority: 100
|
||||||
- id: Testnet
|
- id: Testnet
|
||||||
chain-id: 0x0
|
chain-id: pion-1
|
||||||
short-names: [ neutron-testnet ]
|
short-names: [ neutron-testnet ]
|
||||||
code: NEUTRON_TESTNET
|
code: NEUTRON_TESTNET
|
||||||
grpcId: 10083
|
grpcId: 10083
|
||||||
|
|||||||
@@ -44,16 +44,21 @@ abstract class UpstreamValidator(
|
|||||||
val cp = Comparator { avail1: UpstreamAvailability, avail2: UpstreamAvailability -> if (avail1.isBetterTo(avail2)) -1 else 1 }
|
val cp = Comparator { avail1: UpstreamAvailability, avail2: UpstreamAvailability -> if (avail1.isBetterTo(avail2)) -1 else 1 }
|
||||||
return results.sortedWith(cp).last()
|
return results.sortedWith(cp).last()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resolve(results: Iterable<ValidateUpstreamSettingsResult>): ValidateUpstreamSettingsResult {
|
||||||
|
val cp = Comparator { res1: ValidateUpstreamSettingsResult, res2: ValidateUpstreamSettingsResult -> if (res1.priority < res2.priority) -1 else 1 }
|
||||||
|
return results.sortedWith(cp).last()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ValidateUpstreamSettingsResult {
|
enum class ValidateUpstreamSettingsResult(val priority: Int) {
|
||||||
UPSTREAM_VALID,
|
UPSTREAM_VALID(0),
|
||||||
UPSTREAM_SETTINGS_ERROR,
|
UPSTREAM_SETTINGS_ERROR(1),
|
||||||
UPSTREAM_FATAL_SETTINGS_ERROR,
|
UPSTREAM_FATAL_SETTINGS_ERROR(2),
|
||||||
}
|
}
|
||||||
|
|
||||||
data class SingleCallValidator(
|
data class SingleCallValidator<T>(
|
||||||
val method: ChainRequest,
|
val method: ChainRequest,
|
||||||
val check: (ByteArray) -> UpstreamAvailability,
|
val check: (ByteArray) -> T,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,15 +14,19 @@ import io.emeraldpay.dshackle.upstream.SingleCallValidator
|
|||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability.OK
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability.OK
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
||||||
|
import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult
|
||||||
import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific
|
import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific
|
||||||
import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator
|
import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
import io.emeraldpay.dshackle.upstream.rpcclient.ListParams
|
||||||
import io.emeraldpay.dshackle.upstream.rpcclient.ObjectParams
|
import io.emeraldpay.dshackle.upstream.rpcclient.ObjectParams
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
object CosmosChainSpecific : AbstractPollChainSpecific() {
|
object CosmosChainSpecific : AbstractPollChainSpecific() {
|
||||||
|
|
||||||
|
val log = LoggerFactory.getLogger(this::class.java)
|
||||||
override fun latestBlockRequest(): ChainRequest = ChainRequest("block", ObjectParams())
|
override fun latestBlockRequest(): ChainRequest = ChainRequest("block", ObjectParams())
|
||||||
|
|
||||||
override fun parseBlock(data: ByteArray, upstreamId: String): BlockContainer {
|
override fun parseBlock(data: ByteArray, upstreamId: String): BlockContainer {
|
||||||
@@ -75,9 +79,24 @@ object CosmosChainSpecific : AbstractPollChainSpecific() {
|
|||||||
return GenericUpstreamValidator(
|
return GenericUpstreamValidator(
|
||||||
upstream,
|
upstream,
|
||||||
options,
|
options,
|
||||||
SingleCallValidator(
|
listOf(
|
||||||
ChainRequest("health", ListParams()),
|
SingleCallValidator(
|
||||||
) { _ -> OK },
|
ChainRequest("health", ListParams()),
|
||||||
|
) { _ -> OK },
|
||||||
|
),
|
||||||
|
listOf(
|
||||||
|
SingleCallValidator(
|
||||||
|
ChainRequest("status", ListParams()),
|
||||||
|
) { data ->
|
||||||
|
val resp = Global.objectMapper.readValue(data, CosmosStatus::class.java)
|
||||||
|
if (chain.chainId.isNotEmpty() && resp.nodeInfo.network.lowercase() != chain.chainId.lowercase()) {
|
||||||
|
ValidateUpstreamSettingsResult.UPSTREAM_FATAL_SETTINGS_ERROR
|
||||||
|
} else {
|
||||||
|
ValidateUpstreamSettingsResult.UPSTREAM_VALID
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +134,7 @@ data class CosmosStatus(
|
|||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
data class CosmosNodeInfo(
|
data class CosmosNodeInfo(
|
||||||
@JsonProperty("version") var version: String,
|
@JsonProperty("version") var version: String,
|
||||||
|
@JsonProperty("network") var network: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
|||||||
@@ -8,17 +8,28 @@ import io.emeraldpay.dshackle.upstream.Upstream
|
|||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
||||||
import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult
|
import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult
|
||||||
import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult.UPSTREAM_VALID
|
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import java.util.concurrent.TimeoutException
|
import java.util.concurrent.TimeoutException
|
||||||
|
|
||||||
class GenericUpstreamValidator(
|
class GenericUpstreamValidator(
|
||||||
upstream: Upstream,
|
upstream: Upstream,
|
||||||
options: ChainOptions.Options,
|
options: ChainOptions.Options,
|
||||||
private val validator: SingleCallValidator,
|
private val validators: List<SingleCallValidator<UpstreamAvailability>>,
|
||||||
|
private val startupValidators: List<SingleCallValidator<ValidateUpstreamSettingsResult>>,
|
||||||
) : UpstreamValidator(upstream, options) {
|
) : UpstreamValidator(upstream, options) {
|
||||||
|
|
||||||
override fun validate(): Mono<UpstreamAvailability> {
|
override fun validate(): Mono<UpstreamAvailability> {
|
||||||
|
return Mono.zip(
|
||||||
|
validators.map { exec(it, UpstreamAvailability.UNAVAILABLE) },
|
||||||
|
) { a -> a.map { it as UpstreamAvailability } }
|
||||||
|
.map(::resolve)
|
||||||
|
.defaultIfEmpty(UpstreamAvailability.UNAVAILABLE)
|
||||||
|
.onErrorResume {
|
||||||
|
log.error("Error during upstream validation for ${upstream.getId()}", it)
|
||||||
|
Mono.just(UpstreamAvailability.UNAVAILABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun <T : Any> exec(validator: SingleCallValidator<T>, onError: T): Mono<T> {
|
||||||
return upstream.getIngressReader()
|
return upstream.getIngressReader()
|
||||||
.read(validator.method)
|
.read(validator.method)
|
||||||
.flatMap(ChainResponse::requireResult)
|
.flatMap(ChainResponse::requireResult)
|
||||||
@@ -29,10 +40,22 @@ class GenericUpstreamValidator(
|
|||||||
.then(Mono.error(TimeoutException("Validation timeout for ${validator.method.method}"))),
|
.then(Mono.error(TimeoutException("Validation timeout for ${validator.method.method}"))),
|
||||||
)
|
)
|
||||||
.doOnError { err -> log.error("Error during ${validator.method.method} validation for ${upstream.getId()}", err) }
|
.doOnError { err -> log.error("Error during ${validator.method.method} validation for ${upstream.getId()}", err) }
|
||||||
.onErrorReturn(UpstreamAvailability.UNAVAILABLE)
|
.onErrorReturn(onError)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun validateUpstreamSettings(): Mono<ValidateUpstreamSettingsResult> {
|
override fun validateUpstreamSettings(): Mono<ValidateUpstreamSettingsResult> {
|
||||||
return Mono.just(UPSTREAM_VALID)
|
return Mono.zip(
|
||||||
|
startupValidators.map { exec(it, ValidateUpstreamSettingsResult.UPSTREAM_SETTINGS_ERROR) },
|
||||||
|
) { a -> a.map { it as ValidateUpstreamSettingsResult } }
|
||||||
|
.map(::resolve)
|
||||||
|
.defaultIfEmpty(ValidateUpstreamSettingsResult.UPSTREAM_VALID)
|
||||||
|
.onErrorResume {
|
||||||
|
log.error("Error during upstream validation for ${upstream.getId()}", it)
|
||||||
|
Mono.just(ValidateUpstreamSettingsResult.UPSTREAM_FATAL_SETTINGS_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun validateUpstreamSettingsOnStartup(): ValidateUpstreamSettingsResult {
|
||||||
|
return validateUpstreamSettings().block() ?: ValidateUpstreamSettingsResult.UPSTREAM_VALID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import io.emeraldpay.dshackle.upstream.Upstream
|
|||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamSettingsDetector
|
import io.emeraldpay.dshackle.upstream.UpstreamSettingsDetector
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
||||||
|
import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult
|
||||||
import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific
|
import io.emeraldpay.dshackle.upstream.generic.AbstractPollChainSpecific
|
||||||
import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator
|
import io.emeraldpay.dshackle.upstream.generic.GenericUpstreamValidator
|
||||||
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundService
|
import io.emeraldpay.dshackle.upstream.lowerbound.LowerBoundService
|
||||||
@@ -64,11 +65,20 @@ object NearChainSpecific : AbstractPollChainSpecific() {
|
|||||||
return GenericUpstreamValidator(
|
return GenericUpstreamValidator(
|
||||||
upstream,
|
upstream,
|
||||||
options,
|
options,
|
||||||
SingleCallValidator(
|
listOf(
|
||||||
ChainRequest("status", ListParams()),
|
SingleCallValidator(
|
||||||
) { data ->
|
ChainRequest("status", ListParams()),
|
||||||
validate(data)
|
) { data ->
|
||||||
},
|
validate(data)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
listOf(
|
||||||
|
SingleCallValidator(
|
||||||
|
ChainRequest("status", ListParams()),
|
||||||
|
) { data ->
|
||||||
|
validateSettings(data, chain)
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +95,15 @@ object NearChainSpecific : AbstractPollChainSpecific() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun validateSettings(data: ByteArray, chain: Chain): ValidateUpstreamSettingsResult {
|
||||||
|
val resp = Global.objectMapper.readValue(data, NearStatus::class.java)
|
||||||
|
return if (chain.chainId.isNotEmpty() && resp.chainId.lowercase() != chain.chainId.lowercase()) {
|
||||||
|
ValidateUpstreamSettingsResult.UPSTREAM_FATAL_SETTINGS_ERROR
|
||||||
|
} else {
|
||||||
|
ValidateUpstreamSettingsResult.UPSTREAM_VALID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun upstreamSettingsDetector(chain: Chain, upstream: Upstream): UpstreamSettingsDetector {
|
override fun upstreamSettingsDetector(chain: Chain, upstream: Upstream): UpstreamSettingsDetector {
|
||||||
return NearUpstreamSettingsDetector(upstream)
|
return NearUpstreamSettingsDetector(upstream)
|
||||||
}
|
}
|
||||||
@@ -108,6 +127,7 @@ data class NearHeader(
|
|||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
data class NearStatus(
|
data class NearStatus(
|
||||||
|
@JsonProperty("chain_id") var chainId: String,
|
||||||
@JsonProperty("sync_info") var syncInfo: NearSync,
|
@JsonProperty("sync_info") var syncInfo: NearSync,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import io.emeraldpay.dshackle.upstream.SingleCallValidator
|
|||||||
import io.emeraldpay.dshackle.upstream.Upstream
|
import io.emeraldpay.dshackle.upstream.Upstream
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||||
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
import io.emeraldpay.dshackle.upstream.UpstreamValidator
|
||||||
|
import io.emeraldpay.dshackle.upstream.ValidateUpstreamSettingsResult
|
||||||
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
import io.emeraldpay.dshackle.upstream.calls.CallMethods
|
||||||
import io.emeraldpay.dshackle.upstream.calls.DefaultPolkadotMethods
|
import io.emeraldpay.dshackle.upstream.calls.DefaultPolkadotMethods
|
||||||
import io.emeraldpay.dshackle.upstream.ethereum.WsSubscriptions
|
import io.emeraldpay.dshackle.upstream.ethereum.WsSubscriptions
|
||||||
@@ -97,11 +98,20 @@ object PolkadotChainSpecific : AbstractPollChainSpecific() {
|
|||||||
return GenericUpstreamValidator(
|
return GenericUpstreamValidator(
|
||||||
upstream,
|
upstream,
|
||||||
options,
|
options,
|
||||||
SingleCallValidator(
|
listOf(
|
||||||
ChainRequest("system_health", ListParams()),
|
SingleCallValidator(
|
||||||
) { data ->
|
ChainRequest("system_health", ListParams()),
|
||||||
validate(data, options.minPeers, upstream.getId())
|
) { data ->
|
||||||
},
|
validate(data, options.minPeers, upstream.getId())
|
||||||
|
},
|
||||||
|
),
|
||||||
|
listOf(
|
||||||
|
SingleCallValidator(
|
||||||
|
ChainRequest("system_chain", ListParams()),
|
||||||
|
) { data ->
|
||||||
|
validateSettings(data, chain)
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +133,15 @@ object PolkadotChainSpecific : AbstractPollChainSpecific() {
|
|||||||
return UpstreamAvailability.OK
|
return UpstreamAvailability.OK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun validateSettings(data: ByteArray, chain: Chain): ValidateUpstreamSettingsResult {
|
||||||
|
val id = Global.objectMapper.readValue(data, String::class.java)
|
||||||
|
return if (chain.chainId.isNotEmpty() && id.lowercase() != chain.chainId.lowercase()) {
|
||||||
|
ValidateUpstreamSettingsResult.UPSTREAM_FATAL_SETTINGS_ERROR
|
||||||
|
} else {
|
||||||
|
ValidateUpstreamSettingsResult.UPSTREAM_VALID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun makeIngressSubscription(ws: WsSubscriptions): IngressSubscription {
|
override fun makeIngressSubscription(ws: WsSubscriptions): IngressSubscription {
|
||||||
return GenericIngressSubscription(ws, DefaultPolkadotMethods.subs.map { it.first })
|
return GenericIngressSubscription(ws, DefaultPolkadotMethods.subs.map { it.first })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,17 +124,20 @@ object SolanaChainSpecific : AbstractChainSpecific() {
|
|||||||
return GenericUpstreamValidator(
|
return GenericUpstreamValidator(
|
||||||
upstream,
|
upstream,
|
||||||
options,
|
options,
|
||||||
SingleCallValidator(
|
listOf(
|
||||||
ChainRequest("getHealth", ListParams()),
|
SingleCallValidator(
|
||||||
) { data ->
|
ChainRequest("getHealth", ListParams()),
|
||||||
val resp = String(data)
|
) { data ->
|
||||||
if (resp == "\"ok\"") {
|
val resp = String(data)
|
||||||
UpstreamAvailability.OK
|
if (resp == "\"ok\"") {
|
||||||
} else {
|
UpstreamAvailability.OK
|
||||||
log.warn("Upstream {} validation failed, solana status is {}", upstream.getId(), resp)
|
} else {
|
||||||
UpstreamAvailability.UNAVAILABLE
|
log.warn("Upstream {} validation failed, solana status is {}", upstream.getId(), resp)
|
||||||
}
|
UpstreamAvailability.UNAVAILABLE
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
listOf(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,11 +65,14 @@ object StarknetChainSpecific : AbstractPollChainSpecific() {
|
|||||||
return GenericUpstreamValidator(
|
return GenericUpstreamValidator(
|
||||||
upstream,
|
upstream,
|
||||||
options,
|
options,
|
||||||
SingleCallValidator(
|
listOf(
|
||||||
ChainRequest("starknet_syncing", ListParams()),
|
SingleCallValidator(
|
||||||
) { data ->
|
ChainRequest("starknet_syncing", ListParams()),
|
||||||
validate(data, config.laggingLagSize, upstream.getId())
|
) { data ->
|
||||||
},
|
validate(data, config.laggingLagSize, upstream.getId())
|
||||||
|
},
|
||||||
|
),
|
||||||
|
listOf(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user