Skip to content

Commit

Permalink
Fix checkpoints builder
Browse files Browse the repository at this point in the history
  • Loading branch information
abdrasulov committed Oct 22, 2024
1 parent 7adc62a commit d33bd73
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 36 deletions.
18 changes: 13 additions & 5 deletions tools/src/main/java/io/horizontalsystems/tools/BuildCheckpoints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import io.horizontalsystems.dashkit.TestNetDash
import io.horizontalsystems.ecash.MainNetECash
import io.horizontalsystems.litecoinkit.MainNetLitecoin
import io.horizontalsystems.litecoinkit.TestNetLitecoin
import java.io.*
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.io.PrintWriter
import java.io.Writer
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
import kotlin.system.exitProcess
Expand All @@ -23,19 +28,19 @@ class BuildCheckpoints : CheckpointSyncer.Listener {
private val syncers = mutableListOf<CheckpointSyncer>().also {
// Bitcoin
it.add(CheckpointSyncer(MainNet(), 2016, 1, this))
it.add(CheckpointSyncer(TestNet(), 2016, 1, this))
// it.add(CheckpointSyncer(TestNet(), 2016, 1, this))

// Bitcoin Cash
it.add(CheckpointSyncer(MainNetBitcoinCash(), 147, 147, this))
it.add(CheckpointSyncer(TestNetBitcoinCash(), 147, 147, this))
// it.add(CheckpointSyncer(TestNetBitcoinCash(), 147, 147, this))

// Dash
it.add(CheckpointSyncer(MainNetDash(), 24, 24, this))
it.add(CheckpointSyncer(TestNetDash(), 24, 24, this))
// it.add(CheckpointSyncer(TestNetDash(), 24, 24, this))

// Litecoin
it.add(CheckpointSyncer(MainNetLitecoin(), 2016, 2, this))
it.add(CheckpointSyncer(TestNetLitecoin(), 2016, 2, this))
// it.add(CheckpointSyncer(TestNetLitecoin(), 2016, 2, this))

// Ecash
it.add(CheckpointSyncer(MainNetECash(), 147, 147, this))
Expand All @@ -57,6 +62,9 @@ class BuildCheckpoints : CheckpointSyncer.Listener {

writeCheckpoints(checkpointFile, checkpoints)

println("Synced: ${syncers.count { it.isSynced }}")
println("Remaining: ${syncers.count { !it.isSynced }}")

if (syncers.none { !it.isSynced }) {
exitProcess(0)
}
Expand Down
67 changes: 36 additions & 31 deletions tools/src/main/java/io/horizontalsystems/tools/CheckpointSyncer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ import io.horizontalsystems.bitcoincore.core.IConnectionManagerListener
import io.horizontalsystems.bitcoincore.extensions.toReversedHex
import io.horizontalsystems.bitcoincore.models.Block
import io.horizontalsystems.bitcoincore.network.Network
import io.horizontalsystems.bitcoincore.network.messages.*
import io.horizontalsystems.bitcoincore.network.messages.GetHeadersMessageSerializer
import io.horizontalsystems.bitcoincore.network.messages.HeadersMessageParser
import io.horizontalsystems.bitcoincore.network.messages.HeadersMessageSerializer
import io.horizontalsystems.bitcoincore.network.messages.InvMessageParser
import io.horizontalsystems.bitcoincore.network.messages.InvMessageSerializer
import io.horizontalsystems.bitcoincore.network.messages.NetworkMessageParser
import io.horizontalsystems.bitcoincore.network.messages.NetworkMessageSerializer
import io.horizontalsystems.bitcoincore.network.messages.PingMessageSerializer
import io.horizontalsystems.bitcoincore.network.messages.VerAckMessageParser
import io.horizontalsystems.bitcoincore.network.messages.VerAckMessageSerializer
import io.horizontalsystems.bitcoincore.network.messages.VersionMessageParser
import io.horizontalsystems.bitcoincore.network.messages.VersionMessageSerializer
import io.horizontalsystems.bitcoincore.network.peer.IPeerTaskHandler
import io.horizontalsystems.bitcoincore.network.peer.Peer
import io.horizontalsystems.bitcoincore.network.peer.PeerGroup
Expand All @@ -17,14 +28,14 @@ import io.horizontalsystems.bitcoincore.storage.BlockHeader
import io.horizontalsystems.dashkit.MainNetDash
import io.horizontalsystems.dashkit.TestNetDash
import io.horizontalsystems.dashkit.X11Hasher
import java.util.*
import java.util.LinkedList
import java.util.concurrent.Executors

class CheckpointSyncer(
private val network: Network,
private val checkpointInterval: Int,
private val checkpointsToKeep: Int,
private val listener: Listener)
private val network: Network,
private val checkpointInterval: Int,
private val blocksToKeep: Int,
private val listener: Listener)
: PeerGroup.Listener, IPeerTaskHandler {

interface Listener {
Expand All @@ -44,9 +55,9 @@ class CheckpointSyncer(

private val lastCheckpointBlock = network.lastCheckpoint.block
private val checkpoints = mutableListOf(lastCheckpointBlock)
private val blocks = LinkedList<Block>().also {
it.add(lastCheckpointBlock)
}
private val blocks = LinkedList(
(listOf(lastCheckpointBlock) + network.lastCheckpoint.additionalBlocks).reversed()
)

init {
val blockHeaderHasher = when (network) {
Expand All @@ -68,6 +79,7 @@ class CheckpointSyncer(
add(InvMessageSerializer())
add(GetHeadersMessageSerializer())
add(HeadersMessageSerializer())
add(PingMessageSerializer())
}

val connectionManager = object : IConnectionManager {
Expand All @@ -93,15 +105,18 @@ class CheckpointSyncer(
fun start() {
isSynced = false
peerGroup.start()
print("Started syncer")
}

// PeerGroup Listener

override fun onPeerConnect(peer: Peer) {
print("onPeerConnect ${peer.host}")
assignNextSyncPeer()
}

override fun onPeerDisconnect(peer: Peer, e: Exception?) {
print("onPeerDisconnect, error: ${e?.message} ${e?.javaClass?.simpleName}")
if (peer == syncPeer) {
syncPeer = null
assignNextSyncPeer()
Expand All @@ -128,12 +143,6 @@ class CheckpointSyncer(
private fun validateHeaders(peer: Peer, headers: Array<BlockHeader>) {
var prevBlock = blocks.last()

if (headers.size < 2000) {
peer.synced = true
downloadBlockchain()
return
}

for (header in headers) {
if (!prevBlock.headerHash.contentEquals(header.previousBlockHeaderHash)) {
syncPeer = null
Expand All @@ -151,32 +160,28 @@ class CheckpointSyncer(
prevBlock = newBlock
}

if (headers.size < 2000) {
peer.synced = true
}

downloadBlockchain()
}

private fun assignNextSyncPeer() {
peersQueue.execute {
if (peerManager.connected().none { !it.synced }) {
print("assignNextSyncPeer, connected peers: ${peerManager.connected().size}")
print("synced peers: ${peerManager.connected().count { it.synced }}")

if (peerManager.connected().all { it.synced }) {
isSynced = true
peerGroup.stop()
print("Synced")

val checkpoint = checkpoints.last()

if (checkpointsToKeep == 1) {
listener.onSync(network, listOf(checkpoint))
return@execute
}

if (checkpoint.height <= blocks.last.height && blocks.size >= checkpointsToKeep) {
val filter = blocks.filter { it.height <= checkpoint.height }
listener.onSync(network, filter.takeLast(checkpointsToKeep).reversed())
}

return@execute
}
val lastCheckpoint = checkpoints.last()
val blocksPrecedingCheckpoint = blocks.dropLastWhile { it.height > lastCheckpoint.height }

if (syncPeer == null) {
listener.onSync(network, blocksPrecedingCheckpoint.reversed().take(blocksToKeep))
} else if (syncPeer == null) {
val notSyncedPeers = peerManager.sorted().filter { !it.synced }
notSyncedPeers.firstOrNull { it.ready }?.let { nonSyncedPeer ->
syncPeer = nonSyncedPeer
Expand Down

0 comments on commit d33bd73

Please sign in to comment.