problem: lag is not observed on bitcoin

This commit is contained in:
Igor Artamonov
2020-09-01 17:09:45 -04:00
parent 966ce7d8db
commit 4e16a8c270
5 changed files with 79 additions and 26 deletions

View File

@@ -21,8 +21,10 @@ import org.slf4j.LoggerFactory
import org.springframework.context.Lifecycle
import reactor.core.Disposable
import reactor.core.publisher.Flux
import reactor.core.scheduler.Schedulers
import reactor.util.function.Tuple2
import reactor.util.function.Tuples
import java.time.Duration
/**
* Observer group of upstreams and defined a distance in blocks (lag) between a leader (best height/difficulty) and
@@ -38,6 +40,7 @@ abstract class HeadLagObserver(
private var current: Disposable? = null
override fun start() {
current?.dispose()
current = subscription().subscribe { }
}
@@ -61,12 +64,15 @@ abstract class HeadLagObserver(
fun probeFollowers(top: BlockContainer): Flux<Tuple2<Long, Upstream>> {
return Flux.fromIterable(followers)
.parallel(followers.size)
.flatMap { mapLagging(top, it, getCurrentBlocks(it)) }
.flatMap { up -> mapLagging(top, up, getCurrentBlocks(up)).subscribeOn(Schedulers.elastic()) }
.sequential()
.onErrorContinue { t, _ -> log.warn("Failed to update lagging distance", t) }
}
abstract fun getCurrentBlocks(up: Upstream): Flux<BlockContainer>
open fun getCurrentBlocks(up: Upstream): Flux<BlockContainer> {
val head = up.getHead()
return head.getFlux().take(Duration.ofSeconds(1))
}
fun mapLagging(top: BlockContainer, up: Upstream, blocks: Flux<BlockContainer>): Flux<Tuple2<Long, Upstream>> {
return blocks
@@ -78,11 +84,14 @@ abstract class HeadLagObserver(
}
}
abstract fun extractDistance(top: BlockContainer, curr: BlockContainer): Long
fun forkDistance(top: BlockContainer, curr: BlockContainer): Long {
//TODO look for common ancestor? though it may be a corruption
return 6
open fun extractDistance(top: BlockContainer, curr: BlockContainer): Long {
return when {
curr.height > top.height -> if (curr.difficulty >= top.difficulty) 0 else forkDistance(top, curr)
curr.height == top.height -> if (curr.difficulty == top.difficulty) 0 else forkDistance(top, curr)
else -> top.height - curr.height
}
}
abstract fun forkDistance(top: BlockContainer, curr: BlockContainer): Long
}

View File

@@ -0,0 +1,38 @@
/**
* 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.upstream.bitcoin
import io.emeraldpay.dshackle.data.BlockContainer
import io.emeraldpay.dshackle.upstream.Head
import io.emeraldpay.dshackle.upstream.HeadLagObserver
import io.emeraldpay.dshackle.upstream.Upstream
import org.slf4j.LoggerFactory
class BitcoinHeadLagObserver(
master: Head,
followers: Collection<Upstream>
) : HeadLagObserver(master, followers) {
companion object {
private val log = LoggerFactory.getLogger(BitcoinHeadLagObserver::class.java)
}
override fun forkDistance(top: BlockContainer, curr: BlockContainer): Long {
//TODO fetch actual blocks
return 3
}
}

View File

@@ -64,8 +64,8 @@ open class BitcoinMultistream(
val newHead = MergedHead(upstreams.map { it.getHead() }).apply {
this.start()
}
// val lagObserver = TODO
// this.lagObserver = lagObserver
val lagObserver = BitcoinHeadLagObserver(newHead, upstreams)
this.lagObserver = lagObserver
newHead
}
onHeadUpdated(head)

View File

@@ -33,16 +33,9 @@ class EthereumHeadLagObserver(
private val log = LoggerFactory.getLogger(EthereumHeadLagObserver::class.java)
}
override fun getCurrentBlocks(up: Upstream): Flux<BlockContainer> {
val head = up.getHead()
return head.getFlux().take(Duration.ofSeconds(1))
override fun forkDistance(top: BlockContainer, curr: BlockContainer): Long {
//TODO look for common ancestor? though it may be a corruption
return 6
}
override fun extractDistance(top: BlockContainer, curr: BlockContainer): Long {
return when {
curr.height > top.height -> if (curr.difficulty >= top.difficulty) 0 else forkDistance(top, curr)
curr.height == top.height -> if (curr.difficulty == top.difficulty) 0 else forkDistance(top, curr)
else -> top.height - curr.height
}
}
}