mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-23 14:50:42 +01:00
* Introduce ChainHandlerCached which behaves like the old ChainHandler. Now Chainhandler.getBestBlockHeader() will read headers from the database * Remove ChainHandler.blockchains field, now it's only available in ChainHandlerCached * De-futurify ChainHandler.fromDatabase() * Adjust logging * Patch test case * Use BlockHeaderDAO.chainTips when getting best header rather thean BlockHeaderDAO.getBlockchains(). Implement a helper method ChainHandler.toChainHandlerCached() * Fix chain.md,wallet.md * Make ChainHandler.getBestBlockHeader() consider time of header if chainwork is the same. Make test cases less strict on what header is the best header when both chainwork and time are the same on the eader * Only execute callbacks on headers that are going to be created in the database, not all headers passed into ChainHandler.processHeadersWithChains() * Turn up log level again * Small optimizations, check if we have seen a header before before processing it in ChainHandler.processHeadersWithChains(). Fix FilterSyncMarker.toString(). Use ChainHandlerCached in Node * Remove ChainHandlerCached in appServer, re-add it in Node.scala
90 lines
2.8 KiB
Markdown
90 lines
2.8 KiB
Markdown
---
|
|
title: Blockchain Verification
|
|
id: chain
|
|
---
|
|
|
|
Bitcoin-S comes bundled with a rudimentary blockchain verification
|
|
module. This module is currently only released as a library, and not as a binary.
|
|
This is because it (nor the documentation) is not deemed production
|
|
ready. Use at your own risk, and without too much money depending on it.
|
|
|
|
## Syncing and verifying block headers
|
|
|
|
Using the `chain` module of Bitcoin-S it's possible to
|
|
sync and verify block headers from the Bitcoin blockchain. In this document
|
|
we demonstrate how to do this, while persisting it to disk. We should be
|
|
able to read this chain on subsequent runs, assuming we are connected
|
|
to the same `bitcoind` instance.
|
|
|
|
```scala mdoc:invisible
|
|
import org.bitcoins.chain.blockchain._
|
|
import org.bitcoins.chain.blockchain.sync._
|
|
import org.bitcoins.chain.models._
|
|
import org.bitcoins.chain.config.ChainAppConfig
|
|
import org.bitcoins.rpc.config.BitcoindInstance
|
|
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
|
import org.bitcoins.rpc.client.common._
|
|
import org.bitcoins.testkit.chain._
|
|
|
|
import scala.concurrent._
|
|
import java.nio.file.Files
|
|
```
|
|
|
|
```scala mdoc:compile-only
|
|
|
|
implicit val ec = ExecutionContext.global
|
|
|
|
// We are assuming that a `bitcoind` regtest node is running the background.
|
|
// You can see our `bitcoind` guides to see how to connect
|
|
// to a local or remote `bitcoind` node.
|
|
|
|
val bitcoindInstance = BitcoindInstance.fromDatadir()
|
|
val rpcCli = BitcoindRpcClient(bitcoindInstance)
|
|
|
|
// Next, we need to create a way to monitor the chain:
|
|
|
|
val getBestBlockHash = SyncUtil.getBestBlockHashFunc(rpcCli)
|
|
|
|
val getBlockHeader = SyncUtil.getBlockHeaderFunc(rpcCli)
|
|
|
|
// set a data directory
|
|
val datadir = Files.createTempDirectory("bitcoin-s-test")
|
|
|
|
// set the current network to regtest
|
|
import com.typesafe.config.ConfigFactory
|
|
val config = ConfigFactory.parseString {
|
|
"""
|
|
| bitcoin-s {
|
|
| network = regtest
|
|
| }
|
|
|""".stripMargin
|
|
}
|
|
|
|
implicit val chainConfig = ChainAppConfig(datadir, config)
|
|
|
|
// Initialize the needed database tables if they don't exist:
|
|
val chainProjectInitF = chainConfig.start()
|
|
val blockHeaderDAO = BlockHeaderDAO()
|
|
val compactFilterHeaderDAO = CompactFilterHeaderDAO()
|
|
val compactFilterDAO = CompactFilterDAO()
|
|
|
|
|
|
//initialize the chain handler from the database
|
|
val chainHandler = ChainHandler.fromDatabase(blockHeaderDAO, compactFilterHeaderDAO, compactFilterDAO)
|
|
|
|
// Now, do the actual syncing:
|
|
val syncedChainApiF = for {
|
|
_ <- chainProjectInitF
|
|
synced <- ChainSync.sync(chainHandler, getBlockHeader, getBestBlockHash)
|
|
} yield synced
|
|
|
|
val syncResultF = syncedChainApiF.flatMap { chainApi =>
|
|
chainApi.getBlockCount().map(count => println(s"chain api blockcount=${count}"))
|
|
|
|
rpcCli.getBlockCount.map(count => println(s"bitcoind blockcount=${count}"))
|
|
}
|
|
|
|
syncResultF.onComplete { case result =>
|
|
println(s"Sync result=${result}")
|
|
}
|
|
```
|