solution: allows to disable upstream validation
This commit is contained in:
@@ -14,6 +14,8 @@ class UpstreamsConfig {
|
|||||||
@Deprecated("remove it")
|
@Deprecated("remove it")
|
||||||
var quorum: Int = 1
|
var quorum: Int = 1
|
||||||
var disableSyncing: Boolean? = null
|
var disableSyncing: Boolean? = null
|
||||||
|
var disableValidation: Boolean? = null
|
||||||
|
|
||||||
var minPeers: Int? = 1
|
var minPeers: Int? = 1
|
||||||
set(minPeers) {
|
set(minPeers) {
|
||||||
if (minPeers != null && minPeers < 0) {
|
if (minPeers != null && minPeers < 0) {
|
||||||
@@ -29,6 +31,7 @@ class UpstreamsConfig {
|
|||||||
val copy = Options()
|
val copy = Options()
|
||||||
copy.disableSyncing = if (this.disableSyncing != null) this.disableSyncing else additional.disableSyncing
|
copy.disableSyncing = if (this.disableSyncing != null) this.disableSyncing else additional.disableSyncing
|
||||||
copy.minPeers = if (this.minPeers != null) this.minPeers else additional.minPeers
|
copy.minPeers = if (this.minPeers != null) this.minPeers else additional.minPeers
|
||||||
|
copy.disableValidation = if (this.disableValidation != null) this.disableValidation else additional.disableValidation
|
||||||
return copy
|
return copy
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +40,7 @@ class UpstreamsConfig {
|
|||||||
val options = Options()
|
val options = Options()
|
||||||
options.disableSyncing = true
|
options.disableSyncing = true
|
||||||
options.minPeers = 1
|
options.minPeers = 1
|
||||||
|
options.disableValidation = false
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,15 +29,8 @@ class UpstreamsConfigReader {
|
|||||||
val defaultOptions = UpstreamsConfig.DefaultOptions()
|
val defaultOptions = UpstreamsConfig.DefaultOptions()
|
||||||
config.defaultOptions.add(defaultOptions)
|
config.defaultOptions.add(defaultOptions)
|
||||||
defaultOptions.chains = getListOfString(opts, "chains")
|
defaultOptions.chains = getListOfString(opts, "chains")
|
||||||
val options = UpstreamsConfig.Options()
|
|
||||||
defaultOptions.options = options
|
|
||||||
getMapping(opts, "options")?.let { values ->
|
getMapping(opts, "options")?.let { values ->
|
||||||
getValueAsBool(values, "disable-syncing")?.let {
|
defaultOptions.options = readOptions(values)
|
||||||
options.disableSyncing = it
|
|
||||||
}
|
|
||||||
getValueAsInt(values, "min-peers")?.let {
|
|
||||||
options.minPeers = it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +88,7 @@ class UpstreamsConfigReader {
|
|||||||
|
|
||||||
internal fun readUpstreamCommon(upNode: MappingNode, upstream: UpstreamsConfig.Upstream<*>) {
|
internal fun readUpstreamCommon(upNode: MappingNode, upstream: UpstreamsConfig.Upstream<*>) {
|
||||||
upstream.id = getValueAsString(upNode, "id")
|
upstream.id = getValueAsString(upNode, "id")
|
||||||
|
upstream.options = tryReadOptions(upNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun readUpstreamGrpc(upNode: MappingNode, upstream: UpstreamsConfig.Upstream<UpstreamsConfig.GrpcConnection>) {
|
internal fun readUpstreamGrpc(upNode: MappingNode, upstream: UpstreamsConfig.Upstream<UpstreamsConfig.GrpcConnection>) {
|
||||||
@@ -122,6 +116,30 @@ class UpstreamsConfigReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun tryReadOptions(upNode: MappingNode): UpstreamsConfig.Options? {
|
||||||
|
return if (hasAny(upNode, "options")) {
|
||||||
|
return getMapping(upNode, "options")?.let { values ->
|
||||||
|
readOptions(values)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun readOptions(values: MappingNode): UpstreamsConfig.Options {
|
||||||
|
val options = UpstreamsConfig.Options()
|
||||||
|
getValueAsBool(values, "disable-syncing")?.let {
|
||||||
|
options.disableSyncing = it
|
||||||
|
}
|
||||||
|
getValueAsInt(values, "min-peers")?.let {
|
||||||
|
options.minPeers = it
|
||||||
|
}
|
||||||
|
getValueAsBool(values, "disable-validation")?.let {
|
||||||
|
options.disableValidation = it
|
||||||
|
}
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
private fun readAuth(authNode: MappingNode?): UpstreamsConfig.Auth? {
|
private fun readAuth(authNode: MappingNode?): UpstreamsConfig.Auth? {
|
||||||
return getValueAsString(authNode, "type")?.let {
|
return getValueAsString(authNode, "type")?.let {
|
||||||
return when (it) {
|
return when (it) {
|
||||||
|
|||||||
@@ -47,13 +47,17 @@ open class ConfiguredUpstreams(
|
|||||||
val config = readConfig()
|
val config = readConfig()
|
||||||
val defaultOptions = buildDefaultOptions(config)
|
val defaultOptions = buildDefaultOptions(config)
|
||||||
config.upstreams.forEach { up ->
|
config.upstreams.forEach { up ->
|
||||||
val options = (up.options ?: UpstreamsConfig.Options())
|
|
||||||
.merge(UpstreamsConfig.Options.getDefaults())
|
|
||||||
|
|
||||||
if (up.connection is UpstreamsConfig.GrpcConnection) {
|
if (up.connection is UpstreamsConfig.GrpcConnection) {
|
||||||
buildGrpcUpstream(up.connection as UpstreamsConfig.GrpcConnection, options)
|
buildGrpcUpstream(up.connection as UpstreamsConfig.GrpcConnection)
|
||||||
} else {
|
} else {
|
||||||
val chain = chainNames[up.chain] ?: return
|
val chain = chainNames[up.chain]
|
||||||
|
if (chain == null) {
|
||||||
|
log.error("Chain not supported: ${up.chain}")
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
val options = (up.options ?: UpstreamsConfig.Options())
|
||||||
|
.merge(defaultOptions[chain] ?: UpstreamsConfig.Options.getDefaults())
|
||||||
buildEthereumUpstream(up.connection as UpstreamsConfig.EthereumConnection, chain, options, up.labels)
|
buildEthereumUpstream(up.connection as UpstreamsConfig.EthereumConnection, chain, options, up.labels)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,19 +82,22 @@ open class ConfiguredUpstreams(
|
|||||||
|
|
||||||
private fun buildDefaultOptions(config: UpstreamsConfig): HashMap<Chain, UpstreamsConfig.Options> {
|
private fun buildDefaultOptions(config: UpstreamsConfig): HashMap<Chain, UpstreamsConfig.Options> {
|
||||||
val defaultOptions = HashMap<Chain, UpstreamsConfig.Options>()
|
val defaultOptions = HashMap<Chain, UpstreamsConfig.Options>()
|
||||||
config.defaultOptions.forEach { df ->
|
config.defaultOptions.forEach { defaultsConfig ->
|
||||||
df.chains?.forEach { chainName ->
|
defaultsConfig.chains?.forEach { chainName ->
|
||||||
chainNames[chainName]?.let { chain ->
|
chainNames[chainName]?.let { chain ->
|
||||||
var current = defaultOptions[chain]
|
defaultsConfig.options?.let { options ->
|
||||||
if (current == null) {
|
if (!defaultOptions.containsKey(chain)) {
|
||||||
current = df.options
|
defaultOptions[chain] = options
|
||||||
} else {
|
} else {
|
||||||
current = current.merge(df.options)
|
defaultOptions[chain] = defaultOptions[chain]!!.merge(options)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defaultOptions[chain] = current!!
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
defaultOptions.keys.forEach { chain ->
|
||||||
|
defaultOptions[chain] = defaultOptions[chain]!!.merge(UpstreamsConfig.Options.getDefaults())
|
||||||
|
}
|
||||||
return defaultOptions
|
return defaultOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,13 +136,12 @@ open class ConfiguredUpstreams(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildGrpcUpstream(up: UpstreamsConfig.GrpcConnection, options: UpstreamsConfig.Options) {
|
private fun buildGrpcUpstream(up: UpstreamsConfig.GrpcConnection) {
|
||||||
val endpoint = up
|
val endpoint = up
|
||||||
val ds = GrpcUpstreams(
|
val ds = GrpcUpstreams(
|
||||||
endpoint.host!!,
|
endpoint.host!!,
|
||||||
endpoint.port ?: 443,
|
endpoint.port ?: 443,
|
||||||
objectMapper,
|
objectMapper,
|
||||||
options,
|
|
||||||
up.auth,
|
up.auth,
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,16 +23,20 @@ open class EthereumUpstream(
|
|||||||
|
|
||||||
private val log = LoggerFactory.getLogger(EthereumUpstream::class.java)
|
private val log = LoggerFactory.getLogger(EthereumUpstream::class.java)
|
||||||
|
|
||||||
private val head: EthereumHead = createHead()
|
private val head: EthereumHead = this.createHead()
|
||||||
|
|
||||||
private val validator = UpstreamValidator(this, options)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
log.info("Configured for ${chain.chainName}")
|
log.info("Configured for ${chain.chainName}")
|
||||||
api.upstream = this
|
api.upstream = this
|
||||||
|
|
||||||
validator.start()
|
if (options.disableValidation != null && options.disableValidation!!) {
|
||||||
.subscribe(this::setStatus)
|
this.setLag(0)
|
||||||
|
this.setStatus(UpstreamAvailability.OK)
|
||||||
|
} else {
|
||||||
|
val validator = UpstreamValidator(this, options)
|
||||||
|
validator.start()
|
||||||
|
.subscribe(this::setStatus)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun createHead(): EthereumHead {
|
open fun createHead(): EthereumHead {
|
||||||
|
|||||||
@@ -27,15 +27,13 @@ open class GrpcUpstream(
|
|||||||
private val chain: Chain,
|
private val chain: Chain,
|
||||||
private val client: ReactorBlockchainGrpc.ReactorBlockchainStub,
|
private val client: ReactorBlockchainGrpc.ReactorBlockchainStub,
|
||||||
private val objectMapper: ObjectMapper,
|
private val objectMapper: ObjectMapper,
|
||||||
private val options: UpstreamsConfig.Options,
|
|
||||||
private val targets: CallMethods
|
private val targets: CallMethods
|
||||||
): DefaultUpstream() {
|
): DefaultUpstream() {
|
||||||
|
|
||||||
constructor(chain: Chain, client: ReactorBlockchainGrpc.ReactorBlockchainStub, objectMapper: ObjectMapper, targets: CallMethods)
|
|
||||||
: this(chain, client, objectMapper, UpstreamsConfig.Options.getDefaults(), targets)
|
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(GrpcUpstream::class.java)
|
private val log = LoggerFactory.getLogger(GrpcUpstream::class.java)
|
||||||
|
|
||||||
|
private val options = UpstreamsConfig.Options.getDefaults()
|
||||||
private val headBlock = AtomicReference<BlockJson<TransactionId>>(null)
|
private val headBlock = AtomicReference<BlockJson<TransactionId>>(null)
|
||||||
private val streamBlocks: TopicProcessor<BlockJson<TransactionId>> = TopicProcessor.create()
|
private val streamBlocks: TopicProcessor<BlockJson<TransactionId>> = TopicProcessor.create()
|
||||||
private val status = AtomicReference<UpstreamAvailability>(UpstreamAvailability.UNAVAILABLE)
|
private val status = AtomicReference<UpstreamAvailability>(UpstreamAvailability.UNAVAILABLE)
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class GrpcUpstreams(
|
|||||||
private val host: String,
|
private val host: String,
|
||||||
private val port: Int,
|
private val port: Int,
|
||||||
private val objectMapper: ObjectMapper,
|
private val objectMapper: ObjectMapper,
|
||||||
private val options: UpstreamsConfig.Options,
|
|
||||||
private val auth: UpstreamsConfig.TlsAuth? = null,
|
private val auth: UpstreamsConfig.TlsAuth? = null,
|
||||||
private val upstreams: Upstreams
|
private val upstreams: Upstreams
|
||||||
) {
|
) {
|
||||||
@@ -92,7 +91,7 @@ class GrpcUpstreams(
|
|||||||
lock.withLock {
|
lock.withLock {
|
||||||
val current = known[chain]
|
val current = known[chain]
|
||||||
return if (current == null) {
|
return if (current == null) {
|
||||||
val created = GrpcUpstream(chain, client!!, objectMapper, options, upstreams.targetFor(chain))
|
val created = GrpcUpstream(chain, client!!, objectMapper, upstreams.targetFor(chain))
|
||||||
known[chain] = created
|
known[chain] = created
|
||||||
upstreams.addUpstream(chain, created)
|
upstreams.addUpstream(chain, created)
|
||||||
created.connect()
|
created.connect()
|
||||||
|
|||||||
@@ -96,6 +96,22 @@ class UpstreamsConfigReaderSpec extends Specification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "Parse config with options"() {
|
||||||
|
setup:
|
||||||
|
def config = this.class.getClassLoader().getResourceAsStream("upstreams-options.yaml")
|
||||||
|
when:
|
||||||
|
def act = reader.read(config)
|
||||||
|
then:
|
||||||
|
act != null
|
||||||
|
act.upstreams.size() == 2
|
||||||
|
with(act.upstreams.get(0)) {
|
||||||
|
options.minPeers == 7
|
||||||
|
}
|
||||||
|
with(act.upstreams.get(1)) {
|
||||||
|
options.disableValidation == true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def "Post process for usual strings"() {
|
def "Post process for usual strings"() {
|
||||||
expect:
|
expect:
|
||||||
s == reader.postProcess(s)
|
s == reader.postProcess(s)
|
||||||
|
|||||||
33
src/test/resources/upstreams-options.yaml
Normal file
33
src/test/resources/upstreams-options.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
version: v1
|
||||||
|
|
||||||
|
defaultOptions:
|
||||||
|
- chains:
|
||||||
|
- ethereum
|
||||||
|
options:
|
||||||
|
disable-syncing: true
|
||||||
|
min-peers: 3
|
||||||
|
|
||||||
|
upstreams:
|
||||||
|
- id: local
|
||||||
|
chain: ethereum
|
||||||
|
options:
|
||||||
|
min-peers: 7
|
||||||
|
connection:
|
||||||
|
ethereum:
|
||||||
|
rpc:
|
||||||
|
url: "http://localhost:8545"
|
||||||
|
ws:
|
||||||
|
url: "ws://localhost:8546"
|
||||||
|
origin: "http://localhost"
|
||||||
|
- id: infura
|
||||||
|
chain: ethereum
|
||||||
|
options:
|
||||||
|
disable-validation: true
|
||||||
|
connection:
|
||||||
|
ethereum:
|
||||||
|
rpc:
|
||||||
|
url: "https://mainnet.infura.io/v3/fa28c968191849c1aff541ad1d8511f2"
|
||||||
|
auth:
|
||||||
|
type: basic
|
||||||
|
username: 4fc258fe41a68149c199ad8f281f2015
|
||||||
|
password: 1a68f20154fc258fe4149c199ad8f281
|
||||||
Reference in New Issue
Block a user