mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-18 13:24:25 +01:00
Get FilterSync test working with cached bitcoind in chainTest project (#2952)
* Get FilterSync test working with cached bitcoind in chainTest project * Small refactor to be DRY * Fix docs * Refactor ChainSyncTest to use 1 cached bitcoind, as a by product add ChainWithBitcoindNewestCachedUnitTest * Remove unecessary mixin trait * Fix missing ChainWithBitcoindNewestCachedUnitTest.afterAll() * Reduce thread pool size for akka's internal dispatcher in unit tests from 2 -> 1. Same with the blocking dispatcher * Add comment
This commit is contained in:
parent
0cad0edaaf
commit
a27d4acd9f
@ -3,23 +3,20 @@ package org.bitcoins.chain.blockchain.sync
|
||||
import org.bitcoins.chain.blockchain.ChainHandler
|
||||
import org.bitcoins.core.api.chain.ChainApi
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.testkit.chain.fixture.BitcoindChainHandlerViaRpc
|
||||
import org.bitcoins.testkit.chain.{ChainDbUnitTest, SyncUtil}
|
||||
import org.scalatest.FutureOutcome
|
||||
import org.bitcoins.testkit.chain.SyncUtil
|
||||
import org.bitcoins.testkit.chain.fixture.{
|
||||
BitcoindBaseVersionChainHandlerViaRpc,
|
||||
ChainWithBitcoindNewestCachedUnitTest
|
||||
}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class ChainSyncTest extends ChainDbUnitTest {
|
||||
override type FixtureParam = BitcoindChainHandlerViaRpc
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
withBitcoindChainHandlerViaRpc(test)
|
||||
}
|
||||
class ChainSyncTest extends ChainWithBitcoindNewestCachedUnitTest {
|
||||
|
||||
behavior of "ChainSync"
|
||||
|
||||
it must "sync our chain handler when it is not synced with bitcoind" in {
|
||||
bitcoindWithChainHandler: BitcoindChainHandlerViaRpc =>
|
||||
bitcoindWithChainHandler: BitcoindBaseVersionChainHandlerViaRpc =>
|
||||
val bitcoind = bitcoindWithChainHandler.bitcoindRpc
|
||||
val chainHandler = bitcoindWithChainHandler.chainHandler
|
||||
//first we need to implement the 'getBestBlockHashFunc' and 'getBlockHeaderFunc' functions
|
||||
@ -36,14 +33,17 @@ class ChainSyncTest extends ChainDbUnitTest {
|
||||
getBestBlockHashFunc = getBestBlockHashFunc)
|
||||
}
|
||||
|
||||
newChainHandlerF.flatMap { chainHandler =>
|
||||
chainHandler.getBlockCount().map(count => assert(count == 1))
|
||||
|
||||
for {
|
||||
chainHandler <- newChainHandlerF
|
||||
count <- chainHandler.getBlockCount()
|
||||
bitcoindCount <- bitcoind.getBlockCount
|
||||
} yield {
|
||||
assert(bitcoindCount == count)
|
||||
}
|
||||
}
|
||||
|
||||
it must "not fail when syncing a chain handler that is synced with it's external data source" in {
|
||||
bitcoindWithChainHandler: BitcoindChainHandlerViaRpc =>
|
||||
bitcoindWithChainHandler: BitcoindBaseVersionChainHandlerViaRpc =>
|
||||
val bitcoind = bitcoindWithChainHandler.bitcoindRpc
|
||||
val chainHandler = bitcoindWithChainHandler.chainHandler
|
||||
//first we need to implement the 'getBestBlockHashFunc' and 'getBlockHeaderFunc' functions
|
||||
@ -61,9 +61,18 @@ class ChainSyncTest extends ChainDbUnitTest {
|
||||
getBlockHeaderFunc = getBlockHeaderFunc,
|
||||
getBestBlockHashFunc = getBestBlockHashFunc)
|
||||
|
||||
newChainHandlerF.flatMap { chainHandler =>
|
||||
chainHandler.getBlockCount().map(count => assert(count == 0))
|
||||
}
|
||||
val newChainHandler2F = for {
|
||||
newChainHandler <- newChainHandlerF
|
||||
//sync it again to make sure we don't fail
|
||||
newChainHandler2 <- ChainSync.sync(
|
||||
chainHandler = newChainHandler.asInstanceOf[ChainHandler],
|
||||
getBlockHeaderFunc = getBlockHeaderFunc,
|
||||
getBestBlockHashFunc = getBestBlockHashFunc)
|
||||
bitcoinSCount <- newChainHandler2.getBlockCount()
|
||||
bitcoindCount <- bitcoind.getBlockCount
|
||||
} yield assert(bitcoinSCount == bitcoindCount)
|
||||
|
||||
newChainHandler2F
|
||||
}
|
||||
|
||||
it must "be able to call sync() twice and not fail when nothing has happened" in {
|
||||
@ -87,13 +96,15 @@ class ChainSyncTest extends ChainDbUnitTest {
|
||||
}
|
||||
|
||||
val assertion1F = for {
|
||||
hashes <- generate1F
|
||||
_ <- generate1F
|
||||
chainApiSync1 <- sync1F
|
||||
count <- chainApiSync1.getBlockCount()
|
||||
bestHash <- chainApiSync1.getBestBlockHash()
|
||||
bitcoindBlockCount <- bitcoind.getBlockCount
|
||||
bitcoindBestBlockHash <- bitcoind.getBestBlockHash
|
||||
} yield {
|
||||
assert(count == 1)
|
||||
assert(bestHash == hashes.head)
|
||||
assert(count == bitcoindBlockCount)
|
||||
assert(bestHash == bitcoindBestBlockHash)
|
||||
}
|
||||
|
||||
//let's call sync again and make sure nothing bad happens
|
||||
@ -106,11 +117,13 @@ class ChainSyncTest extends ChainDbUnitTest {
|
||||
getBlockHeaderFunc = getBlockHeaderFunc,
|
||||
getBestBlockHashFunc = getBestBlockHashFunc)
|
||||
count <- chainApiSync2.getBlockCount()
|
||||
hashes <- generate1F
|
||||
_ <- generate1F
|
||||
bestHash <- chainApiSync2.getBestBlockHash()
|
||||
bitcoindBlockCount <- bitcoind.getBlockCount
|
||||
bitcoindBestBlockHash <- bitcoind.getBestBlockHash
|
||||
} yield {
|
||||
assert(count == 1)
|
||||
assert(bestHash == hashes.head)
|
||||
assert(count == bitcoindBlockCount)
|
||||
assert(bestHash == bitcoindBestBlockHash)
|
||||
}
|
||||
|
||||
sync2F
|
||||
|
@ -4,19 +4,15 @@ import org.bitcoins.chain.blockchain.ChainHandler
|
||||
import org.bitcoins.core.api.chain.ChainApi
|
||||
import org.bitcoins.core.gcs.FilterType
|
||||
import org.bitcoins.core.protocol.blockchain.BlockHeader
|
||||
import org.bitcoins.testkit.chain.fixture.BitcoindV19ChainHandler
|
||||
import org.bitcoins.testkit.chain.{ChainDbUnitTest, SyncUtil}
|
||||
import org.scalatest.FutureOutcome
|
||||
import org.bitcoins.testkit.chain.SyncUtil
|
||||
import org.bitcoins.testkit.chain.fixture.{
|
||||
BitcoindV19ChainHandler,
|
||||
ChainWithBitcoindV19CachedUnitTest
|
||||
}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class FilterSyncTest extends ChainDbUnitTest {
|
||||
|
||||
override type FixtureParam = BitcoindV19ChainHandler
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
withBitcoindV19ChainHandlerViaRpc(test)
|
||||
}
|
||||
class FilterSyncTest extends ChainWithBitcoindV19CachedUnitTest {
|
||||
|
||||
behavior of "FilterSync"
|
||||
|
||||
@ -25,19 +21,25 @@ class FilterSyncTest extends ChainDbUnitTest {
|
||||
|
||||
val initFilterCountF = chainHandler.getFilterCount()
|
||||
val initFilterHeaderCountF = chainHandler.getFilterHeaderCount()
|
||||
|
||||
val bitcoindFilterCountF = bitcoind.getFilterCount()
|
||||
|
||||
val initAssertionsF = for {
|
||||
initFilterCount <- initFilterCountF
|
||||
initFilterHeaderCount <- initFilterHeaderCountF
|
||||
bitcoindFilterCount <- bitcoindFilterCountF
|
||||
} yield {
|
||||
assert(initFilterCount == 0)
|
||||
assert(initFilterHeaderCount == 0)
|
||||
assert(initFilterCount == bitcoindFilterCount)
|
||||
assert(initFilterHeaderCount == bitcoindFilterCount)
|
||||
}
|
||||
|
||||
val generated1BlockF = for {
|
||||
_ <- initAssertionsF
|
||||
addr <- bitcoind.getNewAddress
|
||||
hashes <- bitcoind.generateToAddress(1, addr)
|
||||
} yield hashes
|
||||
} yield {
|
||||
hashes
|
||||
}
|
||||
|
||||
val syncedF = generated1BlockF.flatMap { _ =>
|
||||
syncHelper(fixture)
|
||||
@ -46,9 +48,10 @@ class FilterSyncTest extends ChainDbUnitTest {
|
||||
for {
|
||||
syncedChainApi <- syncedF
|
||||
filterHeaderCount <- syncedChainApi.getFilterHeaderCount()
|
||||
_ = assert(filterHeaderCount == 1)
|
||||
bitcoindFilterCount <- bitcoind.getFilterCount()
|
||||
_ = assert(filterHeaderCount == bitcoindFilterCount)
|
||||
filterCount <- syncedChainApi.getFilterCount()
|
||||
} yield assert(filterCount == 1)
|
||||
} yield assert(filterCount == bitcoindFilterCount)
|
||||
}
|
||||
|
||||
it must "sync a bunch of filter headers from an external data source" in {
|
||||
@ -67,10 +70,11 @@ class FilterSyncTest extends ChainDbUnitTest {
|
||||
|
||||
for {
|
||||
syncedChainApi <- syncedF
|
||||
bitcoindFilterCount <- bitcoind.getFilterCount()
|
||||
filterHeaderCount <- syncedChainApi.getFilterHeaderCount()
|
||||
_ = assert(filterHeaderCount == numBlocks)
|
||||
_ = assert(filterHeaderCount == bitcoindFilterCount)
|
||||
filterCount <- syncedChainApi.getFilterCount()
|
||||
} yield assert(filterCount == numBlocks)
|
||||
} yield assert(filterCount == bitcoindFilterCount)
|
||||
}
|
||||
|
||||
it must "be able to call filterSync() and not fail when nothing has happened" in {
|
||||
@ -93,10 +97,11 @@ class FilterSyncTest extends ChainDbUnitTest {
|
||||
|
||||
for {
|
||||
syncedChainApi <- sync2F
|
||||
bitcoindFilterCount <- bitcoind.getFilterCount()
|
||||
filterHeaderCount <- syncedChainApi.getFilterHeaderCount()
|
||||
_ = assert(filterHeaderCount == 1)
|
||||
_ = assert(filterHeaderCount == bitcoindFilterCount)
|
||||
filterCount <- syncedChainApi.getFilterCount()
|
||||
} yield assert(filterCount == 1)
|
||||
} yield assert(filterCount == bitcoindFilterCount)
|
||||
}
|
||||
|
||||
private def syncHelper(
|
||||
@ -111,10 +116,10 @@ class FilterSyncTest extends ChainDbUnitTest {
|
||||
SyncUtil.getFilterFunc(bitcoind, filterType)
|
||||
|
||||
//first sync the chain
|
||||
val syncedHeadersF = ChainSync.sync(chainHandler = chainHandler,
|
||||
getBlockHeaderFunc = getBlockHeaderFunc,
|
||||
getBestBlockHashFunc =
|
||||
getBestBlockHashFunc)
|
||||
val syncedHeadersF: Future[ChainApi] = ChainSync.sync(
|
||||
chainHandler = chainHandler,
|
||||
getBlockHeaderFunc = getBlockHeaderFunc,
|
||||
getBestBlockHashFunc = getBestBlockHashFunc)
|
||||
|
||||
//now sync filters
|
||||
syncedHeadersF.flatMap { syncedChainHandler =>
|
||||
|
@ -68,7 +68,6 @@ abstract class ChainSync extends ChainVerificationLogger {
|
||||
getBlockHeaderFunc: DoubleSha256DigestBE => Future[BlockHeader])(implicit
|
||||
ec: ExecutionContext): Future[ChainApi] = {
|
||||
require(tips.nonEmpty, s"Cannot sync without the genesis block")
|
||||
|
||||
//we need to walk backwards on the chain until we get to one of our tips
|
||||
val tipsBH = tips.map(_.blockHeader)
|
||||
|
||||
|
@ -34,7 +34,6 @@ abstract class FilterSync extends ChainVerificationLogger {
|
||||
batchSize: Int = 25)(implicit
|
||||
ec: ExecutionContext,
|
||||
chainAppConfig: ChainAppConfig): Future[ChainApi] = {
|
||||
|
||||
val ourBestFilterHeaderOptF = chainApi.getBestFilterHeader()
|
||||
val ourBestBlockHeaderF = chainApi.getBestBlockHeader()
|
||||
for {
|
||||
@ -96,7 +95,17 @@ abstract class FilterSync extends ChainVerificationLogger {
|
||||
missing <- chainApi.getHeadersBetween(from = bestFilterBlockHeader.get,
|
||||
to = ourBestHeader)
|
||||
} yield {
|
||||
missing
|
||||
//getHeaderBetween is inclusive with 'from' parameter,
|
||||
//we only want the inclusive behavior when we are fetching
|
||||
//from the genesis block hash, so we can get the genesis filter
|
||||
//else we need the _next_ header after our bestFilterBlockHeader
|
||||
if (
|
||||
bestFilterBlockHeader.get.hashBE == chainAppConfig.chain.genesisHashBE
|
||||
) {
|
||||
missing
|
||||
} else {
|
||||
missing.tail
|
||||
}
|
||||
}
|
||||
|
||||
//because filters can be really large, we don't want to process too many
|
||||
|
@ -5,7 +5,8 @@ import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
|
||||
/** Represents a [[GolombFilter]] with it's [[org.bitcoins.core.gcs.FilterHeader]] associated with it
|
||||
* This is needed because bitcoin core's 'getblockfilter' rpc returns things in this structure
|
||||
* @see https://developer.bitcoin.org/reference/rpc/getblockfilter.html#argument-2-filtertype
|
||||
*/
|
||||
case class FilterWithHeaderHash(
|
||||
filter: GolombFilter,
|
||||
headerHash: DoubleSha256DigestBE)
|
||||
filterHeaderHash: DoubleSha256DigestBE)
|
||||
|
@ -64,7 +64,7 @@ implicit val chainAppConfig = BitcoinSTestAppConfig.getNeutrinoTestConfig().chai
|
||||
val bitcoindWithChainApiF: Future[BitcoindV19ChainHandler] = {
|
||||
ChainUnitTest.createBitcoindV19ChainHandler()
|
||||
}
|
||||
val bitcoindF = bitcoindWithChainApiF.map(_.bitcoind)
|
||||
val bitcoindF = bitcoindWithChainApiF.map(_.bitcoindRpc)
|
||||
val chainApiF = bitcoindWithChainApiF.map(_.chainHandler)
|
||||
|
||||
val filterType = FilterType.Basic
|
||||
|
@ -173,6 +173,7 @@ akka {
|
||||
|
||||
event-stream=off
|
||||
}
|
||||
# https://doc.akka.io/docs/akka/current/dispatchers.html#classic-dispatchers
|
||||
default-dispatcher {
|
||||
# The goal here is to reduce the number of threads spun up for test suites.
|
||||
# Since every test suite currently
|
||||
@ -194,20 +195,20 @@ akka {
|
||||
executor = "thread-pool-executor"
|
||||
throughput = 1
|
||||
thread-pool-executor {
|
||||
fixed-pool-size = 2
|
||||
fixed-pool-size = 1
|
||||
}
|
||||
}
|
||||
internal-dispatcher {
|
||||
# minimum of one thread for tests
|
||||
parallelism-min = 1
|
||||
|
||||
# maximum of 2 threads for tests
|
||||
parallelism-max = 2
|
||||
# maximum of 1 threads for tests
|
||||
parallelism-max = 1
|
||||
type = "Dispatcher"
|
||||
executor = "thread-pool-executor"
|
||||
throughput = 1
|
||||
thread-pool-executor {
|
||||
fixed-pool-size = 2
|
||||
fixed-pool-size = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package org.bitcoins.testkit.chain
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import akka.actor.ActorSystem
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import org.bitcoins.chain.ChainVerificationLogger
|
||||
import org.bitcoins.chain.blockchain.{ChainHandler, ChainHandlerCached}
|
||||
import org.bitcoins.chain.blockchain.sync.ChainSync
|
||||
import org.bitcoins.chain.blockchain.{ChainHandler, ChainHandlerCached}
|
||||
import org.bitcoins.chain.config.ChainAppConfig
|
||||
import org.bitcoins.chain.models._
|
||||
import org.bitcoins.chain.pow.Pow
|
||||
@ -33,9 +32,10 @@ import org.bitcoins.zmq.ZMQSubscriber
|
||||
import org.scalatest._
|
||||
import play.api.libs.json.{JsError, JsSuccess, Json}
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import scala.annotation.tailrec
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait ChainUnitTest
|
||||
extends BitcoinSFixture
|
||||
@ -271,7 +271,7 @@ trait ChainUnitTest
|
||||
bitcoindChainHandler: BitcoindChainHandlerViaZmq): Future[Unit] = {
|
||||
|
||||
//piggy back off of rpc destructor
|
||||
val rpc = chain.fixture.BitcoindChainHandlerViaRpc(
|
||||
val rpc = chain.fixture.BitcoindBaseVersionChainHandlerViaRpc(
|
||||
bitcoindChainHandler.bitcoindRpc,
|
||||
bitcoindChainHandler.chainHandler)
|
||||
|
||||
@ -300,7 +300,7 @@ trait ChainUnitTest
|
||||
|
||||
def withBitcoindChainHandlerViaRpc(test: OneArgAsyncTest)(implicit
|
||||
system: ActorSystem): FutureOutcome = {
|
||||
val builder: () => Future[BitcoindChainHandlerViaRpc] = { () =>
|
||||
val builder: () => Future[BitcoindBaseVersionChainHandlerViaRpc] = { () =>
|
||||
BitcoinSFixture
|
||||
.createBitcoind()
|
||||
.flatMap(ChainUnitTest.createChainApiWithBitcoindRpc)
|
||||
@ -310,15 +310,6 @@ trait ChainUnitTest
|
||||
test)
|
||||
}
|
||||
|
||||
def withBitcoindV19ChainHandlerViaRpc(test: OneArgAsyncTest)(implicit
|
||||
system: ActorSystem): FutureOutcome = {
|
||||
val builder: () => Future[BitcoindV19ChainHandler] = { () =>
|
||||
ChainUnitTest.createBitcoindV19ChainHandler()
|
||||
}
|
||||
makeDependentFixture(builder, ChainUnitTest.destroyBitcoindV19ChainApi)(
|
||||
test)
|
||||
}
|
||||
|
||||
final def processHeaders(
|
||||
processorF: Future[ChainApi],
|
||||
headers: Vector[BlockHeader],
|
||||
@ -569,19 +560,20 @@ object ChainUnitTest extends ChainVerificationLogger {
|
||||
|
||||
def createChainApiWithBitcoindRpc(bitcoind: BitcoindRpcClient)(implicit
|
||||
ec: ExecutionContext,
|
||||
chainAppConfig: ChainAppConfig): Future[BitcoindChainHandlerViaRpc] = {
|
||||
chainAppConfig: ChainAppConfig): Future[
|
||||
BitcoindBaseVersionChainHandlerViaRpc] = {
|
||||
val handlerWithGenesisHeaderF =
|
||||
ChainUnitTest.setupHeaderTableWithGenesisHeader()
|
||||
|
||||
val chainHandlerF = handlerWithGenesisHeaderF.map(_._1)
|
||||
|
||||
chainHandlerF.map { handler =>
|
||||
chain.fixture.BitcoindChainHandlerViaRpc(bitcoind, handler)
|
||||
chain.fixture.BitcoindBaseVersionChainHandlerViaRpc(bitcoind, handler)
|
||||
}
|
||||
}
|
||||
|
||||
def destroyBitcoindChainApiViaRpc(
|
||||
bitcoindChainHandler: BitcoindChainHandlerViaRpc)(implicit
|
||||
bitcoindChainHandler: BitcoindBaseVersionChainHandlerViaRpc)(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig): Future[Unit] = {
|
||||
import system.dispatcher
|
||||
@ -591,30 +583,6 @@ object ChainUnitTest extends ChainVerificationLogger {
|
||||
stopBitcoindF.flatMap(_ => dropTableF)
|
||||
}
|
||||
|
||||
def createBitcoindV19ChainHandler()(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig): Future[BitcoindV19ChainHandler] = {
|
||||
import system.dispatcher
|
||||
val bitcoindV = BitcoindVersion.V19
|
||||
BitcoinSFixture
|
||||
.createBitcoind(Some(bitcoindV))
|
||||
.flatMap(createChainApiWithBitcoindRpc)
|
||||
.map { b: BitcoindChainHandlerViaRpc =>
|
||||
BitcoindV19ChainHandler(
|
||||
b.bitcoindRpc.asInstanceOf[BitcoindV19RpcClient],
|
||||
b.chainHandler)
|
||||
}
|
||||
}
|
||||
|
||||
def destroyBitcoindV19ChainApi(
|
||||
bitcoindV19ChainHandler: BitcoindV19ChainHandler)(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig): Future[Unit] = {
|
||||
val b = BitcoindChainHandlerViaRpc(bitcoindV19ChainHandler.bitcoind,
|
||||
bitcoindV19ChainHandler.chainHandler)
|
||||
destroyBitcoindChainApiViaRpc(b)
|
||||
}
|
||||
|
||||
def destroyBitcoind(bitcoind: BitcoindRpcClient)(implicit
|
||||
system: ActorSystem): Future[Unit] = {
|
||||
BitcoindRpcTestUtil.stopServer(bitcoind)
|
||||
@ -685,4 +653,66 @@ object ChainUnitTest extends ChainVerificationLogger {
|
||||
|
||||
ChainSync.sync(chainHandler, getBlockHeaderFunc, getBestBlockHashFunc)
|
||||
}
|
||||
|
||||
def createBitcoindV19ChainHandler()(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig): Future[BitcoindV19ChainHandler] = {
|
||||
import system.dispatcher
|
||||
val bitcoindV = BitcoindVersion.V19
|
||||
val bitcoindF = BitcoinSFixture
|
||||
.createBitcoind(Some(bitcoindV))
|
||||
.map(_.asInstanceOf[BitcoindV19RpcClient])
|
||||
bitcoindF.flatMap(b => createBitcoindV19ChainHandler(b))
|
||||
}
|
||||
|
||||
def createBitcoindV19ChainHandler(
|
||||
bitcoindV19RpcClient: BitcoindV19RpcClient)(implicit
|
||||
ec: ExecutionContext,
|
||||
chainAppConfig: ChainAppConfig): Future[BitcoindV19ChainHandler] = {
|
||||
|
||||
val chainApiWithBitcoindF = createChainApiWithBitcoindV19Rpc(
|
||||
bitcoindV19RpcClient)
|
||||
|
||||
//now sync the chain api to the bitcoind node
|
||||
val syncedBitcoindWithChainHandlerF = for {
|
||||
chainApiWithBitcoind <- chainApiWithBitcoindF
|
||||
bitcoindWithChainHandler <- SyncUtil.syncBitcoindV19WithChainHandler(
|
||||
chainApiWithBitcoind)
|
||||
} yield bitcoindWithChainHandler
|
||||
|
||||
syncedBitcoindWithChainHandlerF
|
||||
}
|
||||
|
||||
private def createChainApiWithBitcoindV19Rpc(
|
||||
bitcoind: BitcoindV19RpcClient)(implicit
|
||||
ec: ExecutionContext,
|
||||
chainAppConfig: ChainAppConfig): Future[BitcoindV19ChainHandler] = {
|
||||
val handlerWithGenesisHeaderF =
|
||||
ChainUnitTest.setupHeaderTableWithGenesisHeader()
|
||||
|
||||
val chainHandlerF = handlerWithGenesisHeaderF.map(_._1)
|
||||
|
||||
chainHandlerF.map { handler =>
|
||||
BitcoindV19ChainHandler(bitcoind, handler)
|
||||
}
|
||||
}
|
||||
|
||||
def destroyBitcoindV19ChainApi(
|
||||
bitcoindV19ChainHandler: BitcoindV19ChainHandler)(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig): Future[Unit] = {
|
||||
val b = BitcoindBaseVersionChainHandlerViaRpc(
|
||||
bitcoindV19ChainHandler.bitcoindRpc,
|
||||
bitcoindV19ChainHandler.chainHandler)
|
||||
destroyBitcoindChainApiViaRpc(b)
|
||||
}
|
||||
|
||||
/** Destroys the chain api, but leaves the bitcoind instance running
|
||||
* so we can cache it
|
||||
*/
|
||||
def destroyChainApi()(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig): Future[Unit] = {
|
||||
ChainUnitTest.destroyAllTables()(chainAppConfig, system.dispatcher)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
package org.bitcoins.testkit.chain
|
||||
|
||||
import org.bitcoins.chain.blockchain.sync.FilterWithHeaderHash
|
||||
import grizzled.slf4j.Logging
|
||||
import org.bitcoins.chain.blockchain.ChainHandler
|
||||
import org.bitcoins.chain.blockchain.sync.{
|
||||
ChainSync,
|
||||
FilterSync,
|
||||
FilterWithHeaderHash
|
||||
}
|
||||
import org.bitcoins.chain.config.ChainAppConfig
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.GetBlockFilterResult
|
||||
import org.bitcoins.core.api.node
|
||||
import org.bitcoins.core.api.node.{NodeApi, NodeChainQueryApi}
|
||||
@ -11,9 +18,13 @@ import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
|
||||
import org.bitcoins.testkit.chain.fixture.{
|
||||
BitcoindBaseVersionChainHandlerViaRpc,
|
||||
BitcoindChainHandlerViaRpc,
|
||||
BitcoindV19ChainHandler
|
||||
}
|
||||
import org.bitcoins.wallet.Wallet
|
||||
import org.bitcoins.wallet.sync.WalletSync
|
||||
import grizzled.slf4j.Logging
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
@ -176,6 +187,57 @@ abstract class SyncUtil extends Logging {
|
||||
getBlockFunc = SyncUtil.getBlockFunc(bitcoind)
|
||||
)
|
||||
}
|
||||
|
||||
/** Syncs the given chain handler to the given bitcoind node.
|
||||
* This does NOT sync this like block filters, as we cannot
|
||||
* determine if the bitcoind version passed to us has support for block filters
|
||||
*/
|
||||
def syncBitcoindWithChainHandler(
|
||||
bitcoindWithChainHandler: BitcoindChainHandlerViaRpc)(implicit
|
||||
ec: ExecutionContext): Future[BitcoindBaseVersionChainHandlerViaRpc] = {
|
||||
val getBestBlockHash = getBestBlockHashFunc(
|
||||
bitcoindWithChainHandler.bitcoindRpc)
|
||||
val getBlockHeader = getBlockHeaderFunc(
|
||||
bitcoindWithChainHandler.bitcoindRpc)
|
||||
|
||||
val chainApiF = ChainSync.sync(bitcoindWithChainHandler.chainHandler,
|
||||
getBlockHeader,
|
||||
getBestBlockHash)
|
||||
for {
|
||||
chainApi <- chainApiF
|
||||
} yield BitcoindBaseVersionChainHandlerViaRpc(
|
||||
bitcoindRpc = bitcoindWithChainHandler.bitcoindRpc,
|
||||
chainHandler = chainApi.asInstanceOf[ChainHandler])
|
||||
}
|
||||
|
||||
/** Syncs the given chain handler to the given bitcoind node. This also syncs block filters
|
||||
* since we know a bitcoind v19 node has block filter capability
|
||||
*/
|
||||
def syncBitcoindV19WithChainHandler(
|
||||
bitcoindWithChainHandler: BitcoindV19ChainHandler)(implicit
|
||||
ec: ExecutionContext,
|
||||
chainAppConfig: ChainAppConfig): Future[BitcoindV19ChainHandler] = {
|
||||
val bitcoindV19 = bitcoindWithChainHandler.bitcoindRpc
|
||||
val chainApiF = syncBitcoindWithChainHandler(bitcoindWithChainHandler)
|
||||
.map(_.chainHandler)
|
||||
|
||||
val getFilter: BlockHeader => Future[FilterWithHeaderHash] = {
|
||||
getFilterFunc(bitcoindV19, FilterType.Basic)
|
||||
}
|
||||
|
||||
for {
|
||||
chainApi <- chainApiF
|
||||
filterSyncChainApi <- FilterSync.syncFilters(chainApi, getFilter)
|
||||
bestBlockHash <- bitcoindV19.getBestBlockHash
|
||||
ourBestFilter <- chainApi.getBestFilterHeader()
|
||||
_ = require(
|
||||
bestBlockHash == ourBestFilter.get.blockHashBE,
|
||||
s"We did not sync filter's in our fixture bitcoindBestBlockHash=$bestBlockHash our best filter's blockHash=${ourBestFilter.get.blockHashBE}"
|
||||
)
|
||||
} yield BitcoindV19ChainHandler(
|
||||
bitcoindRpc = bitcoindWithChainHandler.bitcoindRpc,
|
||||
chainHandler = filterSyncChainApi.asInstanceOf[ChainHandler])
|
||||
}
|
||||
}
|
||||
|
||||
object SyncUtil extends SyncUtil
|
||||
|
@ -2,8 +2,23 @@ package org.bitcoins.testkit.chain.fixture
|
||||
|
||||
import org.bitcoins.chain.blockchain.ChainHandler
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
|
||||
|
||||
/** Represents a bitcoind instance paired with a chain handler via rpc */
|
||||
case class BitcoindChainHandlerViaRpc(
|
||||
sealed trait BitcoindChainHandlerViaRpc {
|
||||
def bitcoindRpc: BitcoindRpcClient
|
||||
def chainHandler: ChainHandler
|
||||
}
|
||||
|
||||
/** Represents a bitcoind instance paired with a chain handler via rpc
|
||||
* This is useful for when the bitcoind version doesn't matter, you
|
||||
* just need a generic [[BitcoindRpcClient]]
|
||||
*/
|
||||
case class BitcoindBaseVersionChainHandlerViaRpc(
|
||||
bitcoindRpc: BitcoindRpcClient,
|
||||
chainHandler: ChainHandler)
|
||||
extends BitcoindChainHandlerViaRpc
|
||||
|
||||
case class BitcoindV19ChainHandler(
|
||||
override val bitcoindRpc: BitcoindV19RpcClient,
|
||||
chainHandler: ChainHandler)
|
||||
extends BitcoindChainHandlerViaRpc
|
||||
|
@ -0,0 +1,89 @@
|
||||
package org.bitcoins.testkit.chain.fixture
|
||||
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
|
||||
import org.bitcoins.testkit.chain.{ChainDbUnitTest, ChainUnitTest}
|
||||
import org.bitcoins.testkit.rpc.{
|
||||
CachedBitcoind,
|
||||
CachedBitcoindNewest,
|
||||
CachedBitcoindV19
|
||||
}
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
/** Chain unit test that requires a cached bitcoind type to be injected */
|
||||
trait ChainWithBitcoindUnitTest extends ChainDbUnitTest {
|
||||
_: CachedBitcoind[_] =>
|
||||
|
||||
}
|
||||
|
||||
trait ChainWithBitcoindNewestCachedUnitTest
|
||||
extends ChainWithBitcoindUnitTest
|
||||
with CachedBitcoindNewest {
|
||||
|
||||
override type FixtureParam = BitcoindBaseVersionChainHandlerViaRpc
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val f: Future[Outcome] = for {
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
futOutcome = withBitcoindNewestChainHandlerViaRpc(test, bitcoind)
|
||||
fut <- futOutcome.toFuture
|
||||
} yield fut
|
||||
new FutureOutcome(f)
|
||||
}
|
||||
|
||||
def withBitcoindNewestChainHandlerViaRpc(
|
||||
test: OneArgAsyncTest,
|
||||
bitcoindRpcClient: BitcoindRpcClient): FutureOutcome = {
|
||||
val builder: () => Future[BitcoindBaseVersionChainHandlerViaRpc] = { () =>
|
||||
ChainUnitTest.createChainApiWithBitcoindRpc(bitcoindRpcClient)
|
||||
}
|
||||
val destroy: BitcoindBaseVersionChainHandlerViaRpc => Future[Unit] = {
|
||||
case _: BitcoindBaseVersionChainHandlerViaRpc =>
|
||||
ChainUnitTest.destroyChainApi()
|
||||
}
|
||||
makeDependentFixture(builder, destroy)(test)
|
||||
}
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
super[CachedBitcoindNewest].afterAll()
|
||||
super[ChainWithBitcoindUnitTest].afterAll()
|
||||
}
|
||||
}
|
||||
|
||||
/** Chain Unit test suite that has a cached bitcoind v19 instance */
|
||||
trait ChainWithBitcoindV19CachedUnitTest
|
||||
extends ChainWithBitcoindUnitTest
|
||||
with CachedBitcoindV19 {
|
||||
|
||||
override type FixtureParam = BitcoindV19ChainHandler
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val f: Future[Outcome] = for {
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
futOutcome = withBitcoindV19ChainHandlerViaRpc(test, bitcoind)
|
||||
fut <- futOutcome.toFuture
|
||||
} yield fut
|
||||
new FutureOutcome(f)
|
||||
}
|
||||
|
||||
def withBitcoindV19ChainHandlerViaRpc(
|
||||
test: OneArgAsyncTest,
|
||||
bitcoindV19RpcClient: BitcoindV19RpcClient): FutureOutcome = {
|
||||
val builder: () => Future[BitcoindV19ChainHandler] = { () =>
|
||||
ChainUnitTest.createBitcoindV19ChainHandler(bitcoindV19RpcClient)
|
||||
}
|
||||
|
||||
val destroy: BitcoindV19ChainHandler => Future[Unit] = {
|
||||
case _: BitcoindV19ChainHandler =>
|
||||
ChainUnitTest.destroyChainApi()
|
||||
}
|
||||
makeDependentFixture(builder, destroy)(test)
|
||||
}
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
super[CachedBitcoindV19].afterAll()
|
||||
super[ChainWithBitcoindUnitTest].afterAll()
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import org.bitcoins.core.currency._
|
||||
import org.bitcoins.core.gcs.FilterType
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.core.wallet.utxo.TxoState
|
||||
import org.bitcoins.testkit.rpc.CachedBitcoindV19
|
||||
import org.bitcoins.testkit.wallet.{
|
||||
BitcoinSWalletTestCachedBitcoinV19,
|
||||
WalletWithBitcoindV19
|
||||
@ -14,9 +13,7 @@ import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class ProcessBlockTest
|
||||
extends BitcoinSWalletTestCachedBitcoinV19
|
||||
with CachedBitcoindV19 {
|
||||
class ProcessBlockTest extends BitcoinSWalletTestCachedBitcoinV19 {
|
||||
|
||||
override type FixtureParam = WalletWithBitcoindV19
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user