mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-19 05:43:51 +01:00
Remove Spv code (#4356)
* change node tests to neutrino * get node test working * merge DataMessageHandlerTest and DataMessageHandlerNeutrinoNodeTest * delete unused files * remove commented out spv parts * formatting * delete spv node * remove merkle callback for neutrino node * remove spv node wallet callbacks * formatting * remove SpvWalletApi * replace SpvTestConfig with NeutrinoTestConfig * more replace SpvTestConfig with NeutrinoTestConfig * minor fix * fix tests
This commit is contained in:
parent
b80bf4649e
commit
d8fc8e588f
@ -17,7 +17,7 @@ class AppConfigTest extends BitcoinSAsyncTest {
|
||||
val networkOverride =
|
||||
ConfigFactory.parseString("bitcoin-s.network = testnet3")
|
||||
|
||||
val config = BitcoinSTestAppConfig.getSpvTestConfig(networkOverride)
|
||||
val config = BitcoinSTestAppConfig.getNeutrinoTestConfig(networkOverride)
|
||||
val chainConf = config.chainConf
|
||||
val walletConf = config.walletConf
|
||||
val nodeConf = config.nodeConf
|
||||
@ -31,7 +31,7 @@ class AppConfigTest extends BitcoinSAsyncTest {
|
||||
}
|
||||
|
||||
it must "have the same DB path" in {
|
||||
val conf = BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
val conf = BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
val chainConf = conf.chainConf
|
||||
val walletConf = conf.walletConf
|
||||
val nodeConf = conf.nodeConf
|
||||
@ -40,7 +40,7 @@ class AppConfigTest extends BitcoinSAsyncTest {
|
||||
}
|
||||
|
||||
it must "have distinct databases" in {
|
||||
val conf = BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
val conf = BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
val chainConf = conf.chainConf
|
||||
val walletConf = conf.walletConf
|
||||
val nodeConf = conf.nodeConf
|
||||
|
@ -18,7 +18,7 @@ class CommonRoutesSpec
|
||||
with MockFactory {
|
||||
|
||||
implicit val conf: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
val commonRoutes = CommonRoutes(conf.baseDatadir)
|
||||
|
||||
"CommonRoutes" should {
|
||||
|
@ -14,7 +14,7 @@ class CoreRoutesSpec
|
||||
with MockFactory {
|
||||
|
||||
implicit val conf: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
val coreRoutes = CoreRoutes()
|
||||
|
||||
"Core routes" should {
|
||||
|
@ -23,7 +23,7 @@ class DLCRoutesSpec
|
||||
with MockFactory {
|
||||
|
||||
implicit val conf: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
|
||||
val mockWallet = mock[MockWalletApi]
|
||||
|
||||
|
@ -52,7 +52,7 @@ import scala.concurrent.{ExecutionContext, Future}
|
||||
class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
||||
|
||||
implicit val conf: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
|
||||
implicit val timeout: RouteTestTimeout = RouteTestTimeout(5.seconds)
|
||||
|
||||
|
@ -21,7 +21,7 @@ class WalletRoutesSpec
|
||||
with MockFactory {
|
||||
|
||||
implicit val conf: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
val mockWalletApi = mock[MockWalletApi]
|
||||
|
||||
val walletRoutes: WalletRoutes =
|
||||
|
@ -31,7 +31,6 @@ import org.bitcoins.dlc.node.config.DLCNodeAppConfig
|
||||
import org.bitcoins.dlc.wallet._
|
||||
import org.bitcoins.feeprovider.MempoolSpaceTarget.HourFeeTarget
|
||||
import org.bitcoins.feeprovider._
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
import org.bitcoins.rpc.BitcoindException.InWarmUp
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
@ -45,7 +44,7 @@ import org.bitcoins.wallet.models.SpendingInfoDAO
|
||||
|
||||
import java.time.Instant
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.concurrent.{Await, ExecutionContext, Future, Promise}
|
||||
import scala.concurrent.{Await, Future, Promise}
|
||||
|
||||
class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
||||
override val system: ActorSystem,
|
||||
@ -149,12 +148,11 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
||||
//add callbacks to our uninitialized node
|
||||
val configuredNodeF = for {
|
||||
node <- nodeF
|
||||
wallet <- configuredWalletF
|
||||
initNode <- setBloomFilter(node, wallet)
|
||||
_ <- configuredWalletF
|
||||
} yield {
|
||||
logger.info(
|
||||
s"Done configuring node, it took=${System.currentTimeMillis() - start}ms")
|
||||
initNode
|
||||
node
|
||||
}
|
||||
|
||||
val dlcNodeF = for {
|
||||
@ -345,23 +343,6 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
||||
}
|
||||
}
|
||||
|
||||
private def setBloomFilter(node: Node, wallet: Wallet)(implicit
|
||||
ec: ExecutionContext): Future[Node] = {
|
||||
for {
|
||||
nodeWithBloomFilter <- node match {
|
||||
case spvNode: SpvNode =>
|
||||
for {
|
||||
bloom <- wallet.getBloomFilter()
|
||||
_ = logger.info(
|
||||
s"Got bloom filter with ${bloom.filterSize.toInt} elements")
|
||||
} yield spvNode.setBloomFilter(bloom)
|
||||
case _: Node => Future.successful(node)
|
||||
}
|
||||
} yield {
|
||||
nodeWithBloomFilter
|
||||
}
|
||||
}
|
||||
|
||||
/** This is needed for migrations V2/V3 on the chain project to re-calculate the total work for the chain */
|
||||
private def runChainWorkCalc(force: Boolean)(implicit
|
||||
system: ActorSystem): Future[ChainApi] = {
|
||||
|
@ -45,10 +45,6 @@ object CallbackUtil extends Logging {
|
||||
}
|
||||
}
|
||||
nodeConf.nodeType match {
|
||||
case NodeType.SpvNode =>
|
||||
Future.successful(
|
||||
NodeCallbacks(onTxReceived = Vector(onTx),
|
||||
onBlockHeadersReceived = Vector(onHeaders)))
|
||||
case NodeType.NeutrinoNode =>
|
||||
Future.successful(
|
||||
NodeCallbacks(onTxReceived = Vector(onTx),
|
||||
|
@ -172,9 +172,8 @@ trait DLCWalletApi { self: WalletApi =>
|
||||
def findDLCContacts(alias: String): Future[Vector[DLCContactDb]]
|
||||
}
|
||||
|
||||
/** An HDWallet that supports DLCs and both Neutrino and SPV methods of syncing */
|
||||
/** An HDWallet that supports DLCs and Neutrino method of syncing */
|
||||
trait AnyDLCHDWalletApi
|
||||
extends HDWalletApi
|
||||
with DLCWalletApi
|
||||
with NeutrinoWalletApi
|
||||
with SpvWalletApi
|
||||
|
@ -19,16 +19,12 @@ object NodeType extends StringFactory[NodeType] {
|
||||
override def shortName: String = "neutrino"
|
||||
}
|
||||
|
||||
final case object SpvNode extends InternalImplementationNodeType {
|
||||
override def shortName: String = "spv"
|
||||
}
|
||||
|
||||
final case object BitcoindBackend extends ExternalImplementationNodeType {
|
||||
override def shortName: String = "bitcoind"
|
||||
}
|
||||
|
||||
val all: Vector[NodeType] =
|
||||
Vector(FullNode, NeutrinoNode, SpvNode, BitcoindBackend)
|
||||
Vector(FullNode, NeutrinoNode, BitcoindBackend)
|
||||
|
||||
override def fromStringOpt(str: String): Option[NodeType] = {
|
||||
all.find(state => str.toLowerCase() == state.toString.toLowerCase) match {
|
||||
|
@ -1,23 +0,0 @@
|
||||
package org.bitcoins.core.api.wallet
|
||||
|
||||
import org.bitcoins.core.bloom.BloomFilter
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
/** API for the wallet project.
|
||||
*
|
||||
* This wallet API is BIP44 compliant.
|
||||
*
|
||||
* @see [[https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki BIP44]]
|
||||
*/
|
||||
trait SpvWalletApi { self: WalletApi =>
|
||||
|
||||
/** Recreates the account using BIP-44 approach
|
||||
*/
|
||||
def rescanSPVWallet(): Future[Unit]
|
||||
|
||||
/** Retrieves a bloom filter that that can be sent to a P2P network node
|
||||
* to get information about our transactions, pubkeys and scripts.
|
||||
*/
|
||||
def getBloomFilter(): Future[BloomFilter]
|
||||
}
|
@ -418,11 +418,5 @@ trait WalletApi extends StartStopAsync[WalletApi] {
|
||||
/** An HDWallet that uses Neutrino to sync */
|
||||
trait NeutrinoHDWalletApi extends HDWalletApi with NeutrinoWalletApi
|
||||
|
||||
/** An HDWallet that uses SPV to sync */
|
||||
trait SpvHDWalletApi extends HDWalletApi with SpvWalletApi
|
||||
|
||||
/** An HDWallet that supports both Neutrino and SPV methods of syncing */
|
||||
trait AnyHDWalletApi
|
||||
extends HDWalletApi
|
||||
with NeutrinoWalletApi
|
||||
with SpvWalletApi
|
||||
/** An HDWallet that supports Neutrino method of syncing */
|
||||
trait AnyHDWalletApi extends HDWalletApi with NeutrinoWalletApi
|
||||
|
@ -84,7 +84,7 @@ class DBConfigTest extends BitcoinSAsyncTest {
|
||||
() => None)
|
||||
val mainnetConf = ConfigFactory.parseString("bitcoin-s.network = mainnet")
|
||||
val chainConfig: ChainAppConfig = {
|
||||
BitcoinSTestAppConfig.getSpvTestConfig(mainnetConf).chainConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig(mainnetConf).chainConf
|
||||
}
|
||||
|
||||
assert(chainConfig.network == MainNet)
|
||||
|
@ -72,7 +72,7 @@ As an example, we will show you how to use the `ChainQueryApi` and bitcoind to q
|
||||
implicit val system: ActorSystem = ActorSystem(s"node-api-example")
|
||||
implicit val ec: ExecutionContextExecutor = system.dispatcher
|
||||
implicit val walletConf: WalletAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig().walletConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig().walletConf
|
||||
|
||||
// let's use a helper method to get a v19 bitcoind
|
||||
// and a ChainApi
|
||||
|
@ -49,7 +49,7 @@ As an example, we will show you how to use the `NodeApi` and bitcoind to downloa
|
||||
implicit val system: ActorSystem = ActorSystem(s"node-api-example")
|
||||
implicit val ec: ExecutionContextExecutor = system.dispatcher
|
||||
implicit val walletConf: WalletAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig().walletConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig().walletConf
|
||||
|
||||
// let's use a helper method to get a v19 bitcoind
|
||||
// and a ChainApi
|
||||
|
@ -8,7 +8,7 @@ import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.async.TestAsyncUtil
|
||||
import org.bitcoins.testkit.node.NodeTestWithCachedBitcoindNewest
|
||||
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind
|
||||
import org.bitcoins.testkit.node.fixture.NeutrinoNodeConnectedWithBitcoind
|
||||
import org.bitcoins.testkit.util.TorUtil
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
@ -20,9 +20,9 @@ class BroadcastTransactionTest extends NodeTestWithCachedBitcoindNewest {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
BitcoinSTestAppConfig.getNeutrinoWithEmbeddedDbTestConfig(pgUrl)
|
||||
|
||||
override type FixtureParam = SpvNodeConnectedWithBitcoind
|
||||
override type FixtureParam = NeutrinoNodeConnectedWithBitcoind
|
||||
|
||||
def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val torClientF = if (TorUtil.torEnabled) torF else Future.unit
|
||||
@ -30,7 +30,7 @@ class BroadcastTransactionTest extends NodeTestWithCachedBitcoindNewest {
|
||||
val outcome: Future[Outcome] = for {
|
||||
_ <- torClientF
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
outcome = withSpvNodeConnectedToBitcoindCached(test, bitcoind)(
|
||||
outcome = withNeutrinoNodeConnectedToBitcoindCached(test, bitcoind)(
|
||||
system,
|
||||
getFreshConfig)
|
||||
f <- outcome.toFuture
|
||||
@ -50,7 +50,7 @@ class BroadcastTransactionTest extends NodeTestWithCachedBitcoindNewest {
|
||||
}
|
||||
|
||||
it must "safely broadcast a transaction twice" in { param =>
|
||||
val SpvNodeConnectedWithBitcoind(node, rpc) = param
|
||||
val NeutrinoNodeConnectedWithBitcoind(node, rpc) = param
|
||||
|
||||
for {
|
||||
tx <- createValidTx(rpc)
|
||||
@ -66,7 +66,7 @@ class BroadcastTransactionTest extends NodeTestWithCachedBitcoindNewest {
|
||||
}
|
||||
|
||||
it must "broadcast a transaction" in { param =>
|
||||
val SpvNodeConnectedWithBitcoind(node, rpc) = param
|
||||
val NeutrinoNodeConnectedWithBitcoind(node, rpc) = param
|
||||
|
||||
def hasSeenTx(transaction: Transaction): Future[Boolean] = {
|
||||
rpc
|
||||
|
@ -10,12 +10,12 @@ import org.scalatest.FutureOutcome
|
||||
class DisconnectedPeerTest extends NodeUnitTest {
|
||||
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
BitcoinSTestAppConfig.getNeutrinoWithEmbeddedDbTestConfig(pgUrl)
|
||||
|
||||
override type FixtureParam = SpvNode
|
||||
override type FixtureParam = NeutrinoNode
|
||||
|
||||
def withFixture(test: OneArgAsyncTest): FutureOutcome =
|
||||
withDisconnectedSpvNode(test)(system, getFreshConfig)
|
||||
withDisconnectedNeutrinoNode(test)(system, getFreshConfig)
|
||||
|
||||
it must "fail to broadcast a transaction when disconnected" in { node =>
|
||||
val tx = TransactionGenerators.transaction.sampleSome
|
||||
|
@ -1,124 +0,0 @@
|
||||
package org.bitcoins.node
|
||||
|
||||
import akka.actor.Cancellable
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind
|
||||
import org.bitcoins.testkit.node.{
|
||||
NodeTestUtil,
|
||||
NodeTestWithCachedBitcoindNewest
|
||||
}
|
||||
import org.bitcoins.testkit.util.TorUtil
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
||||
class SpvNodeTest extends NodeTestWithCachedBitcoindNewest {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
|
||||
override type FixtureParam = SpvNodeConnectedWithBitcoind
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val torClientF = if (TorUtil.torEnabled) torF else Future.unit
|
||||
|
||||
val outcomeF: Future[Outcome] = for {
|
||||
_ <- torClientF
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
outcome = withSpvNodeConnectedToBitcoindCached(test, bitcoind)(
|
||||
system,
|
||||
getFreshConfig)
|
||||
f <- outcome.toFuture
|
||||
} yield f
|
||||
new FutureOutcome(outcomeF)
|
||||
}
|
||||
|
||||
behavior of "SpvNode"
|
||||
|
||||
it must "receive notification that a block occurred on the p2p network" in {
|
||||
spvNodeConnectedWithBitcoind: SpvNodeConnectedWithBitcoind =>
|
||||
val spvNode = spvNodeConnectedWithBitcoind.node
|
||||
val bitcoind = spvNodeConnectedWithBitcoind.bitcoind
|
||||
|
||||
val assert1F = for {
|
||||
_ <- spvNode.isConnected(0).map(assert(_))
|
||||
a2 <- spvNode.isInitialized(0).map(assert(_))
|
||||
} yield a2
|
||||
|
||||
val hashF: Future[DoubleSha256DigestBE] = bitcoind.getNewAddress
|
||||
.flatMap(bitcoind.generateToAddress(1, _))
|
||||
.map(_.head)
|
||||
|
||||
//sync our spv node expecting to get that generated hash
|
||||
val spvSyncF = for {
|
||||
_ <- assert1F
|
||||
_ <- hashF
|
||||
sync <- spvNode.sync()
|
||||
} yield sync
|
||||
|
||||
spvSyncF.flatMap { _ =>
|
||||
NodeTestUtil
|
||||
.awaitSync(spvNode, bitcoind)
|
||||
.map(_ => succeed)
|
||||
}
|
||||
}
|
||||
|
||||
it must "stay in sync with a bitcoind instance" in {
|
||||
spvNodeConnectedWithBitcoind: SpvNodeConnectedWithBitcoind =>
|
||||
val spvNode = spvNodeConnectedWithBitcoind.node
|
||||
val bitcoind = spvNodeConnectedWithBitcoind.bitcoind
|
||||
|
||||
//we need to generate 1 block for bitcoind to consider
|
||||
//itself out of IBD. bitcoind will not sendheaders
|
||||
//when it believes itself, or it's peer is in IBD
|
||||
val gen1F =
|
||||
bitcoind.getNewAddress.flatMap(bitcoind.generateToAddress(1, _))
|
||||
|
||||
//this needs to be called to get our peer to send us headers
|
||||
//as they happen with the 'sendheaders' message
|
||||
//both our spv node and our bitcoind node _should_ both be at the genesis block (regtest)
|
||||
//at this point so no actual syncing is happening
|
||||
val initSyncF = gen1F.flatMap { hashes =>
|
||||
val syncF = spvNode.sync()
|
||||
for {
|
||||
_ <- syncF
|
||||
_ <- NodeTestUtil.awaitBestHash(hashes.head, spvNode)
|
||||
} yield ()
|
||||
}
|
||||
|
||||
//start generating a block every 10 seconds with bitcoind
|
||||
//this should result in 5 blocks
|
||||
val startGenF: Future[Cancellable] = initSyncF.map { _ =>
|
||||
//generate a block every 5 seconds
|
||||
//until we have generated 5 total blocks
|
||||
genBlockInterval(bitcoind)
|
||||
}
|
||||
|
||||
startGenF.flatMap { cancel =>
|
||||
//we should expect 5 headers have been announced to us via
|
||||
//the send headers message.
|
||||
val has6BlocksF = RpcUtil.retryUntilSatisfiedF(
|
||||
conditionF = () =>
|
||||
spvNode
|
||||
.chainApiFromDb()
|
||||
.flatMap(_.getBlockCount().map { count =>
|
||||
count == 108
|
||||
}),
|
||||
interval = 250.millis)
|
||||
|
||||
has6BlocksF.map { _ =>
|
||||
val isCanceled = cancel.cancel()
|
||||
if (!isCanceled) {
|
||||
logger.warn(s"Failed to cancel generating blocks on bitcoind")
|
||||
}
|
||||
succeed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package org.bitcoins.node
|
||||
|
||||
import org.bitcoins.asyncutil.AsyncUtil
|
||||
import org.bitcoins.core.currency._
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.node.{
|
||||
NodeTestUtil,
|
||||
NodeTestWithCachedBitcoindNewest,
|
||||
SpvNodeFundedWalletBitcoind
|
||||
}
|
||||
import org.bitcoins.wallet.Wallet
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class SpvNodeWithWalletTest extends NodeTestWithCachedBitcoindNewest {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
|
||||
override type FixtureParam = SpvNodeFundedWalletBitcoind
|
||||
|
||||
def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val outcomeF: Future[Outcome] = for {
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
outcome = withSpvNodeFundedWalletBitcoindCached(
|
||||
test,
|
||||
getBIP39PasswordOpt(),
|
||||
bitcoind)(system, getFreshConfig)
|
||||
f <- outcome.toFuture
|
||||
} yield f
|
||||
new FutureOutcome(outcomeF)
|
||||
}
|
||||
|
||||
val amountFromBitcoind = 1.bitcoin
|
||||
|
||||
it must "load a bloom filter and receive information about received payments" in {
|
||||
param =>
|
||||
val SpvNodeFundedWalletBitcoind(spv, wallet, rpc, _) = param
|
||||
|
||||
for {
|
||||
_ <- wallet.getBloomFilter()
|
||||
address <- wallet.getNewAddress()
|
||||
updatedBloom <- spv.updateBloomFilter(address).map(_.bloomFilter)
|
||||
|
||||
ourTxid <-
|
||||
rpc
|
||||
.sendToAddress(address, amountFromBitcoind)
|
||||
_ <- rpc.generateToAddress(1, junkAddress)
|
||||
_ <- spv.sync()
|
||||
_ <- NodeTestUtil.awaitSync(spv, rpc)
|
||||
|
||||
ourTx <- rpc.getTransaction(ourTxid)
|
||||
|
||||
_ = assert(updatedBloom.isRelevant(ourTx.hex))
|
||||
//wait for bitcoind to propagate us a merkle block
|
||||
//and transactions associated with it
|
||||
//eventually we should have the tx
|
||||
//added to our wallet when this occurs
|
||||
_ <- AsyncUtil.retryUntilSatisfiedF(() =>
|
||||
walletContainsTx(wallet, ourTx.txid))
|
||||
} yield {
|
||||
succeed
|
||||
}
|
||||
}
|
||||
|
||||
private def walletContainsTx(
|
||||
wallet: Wallet,
|
||||
txid: DoubleSha256DigestBE): Future[Boolean] = {
|
||||
val txOptF = wallet.findTransaction(txid)
|
||||
for {
|
||||
txOpt <- txOptF
|
||||
} yield txOpt.isDefined
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package org.bitcoins.node
|
||||
|
||||
import org.bitcoins.core.currency._
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.node.{
|
||||
NodeTestUtil,
|
||||
NodeTestWithCachedBitcoindNewest,
|
||||
SpvNodeFundedWalletBitcoind
|
||||
}
|
||||
import org.bitcoins.testkit.util.TorUtil
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class UpdateBloomFilterTest extends NodeTestWithCachedBitcoindNewest {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
|
||||
override type FixtureParam = SpvNodeFundedWalletBitcoind
|
||||
|
||||
def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val torClientF = if (TorUtil.torEnabled) torF else Future.unit
|
||||
|
||||
val outcome: Future[Outcome] = for {
|
||||
_ <- torClientF
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
outcome = withSpvNodeFundedWalletBitcoindCached(
|
||||
test,
|
||||
getBIP39PasswordOpt(),
|
||||
bitcoind)(system, getFreshConfig)
|
||||
f <- outcome.toFuture
|
||||
} yield f
|
||||
new FutureOutcome(outcome)
|
||||
}
|
||||
|
||||
it must "update the bloom filter with a TX" in { param =>
|
||||
val SpvNodeFundedWalletBitcoind(spv, wallet, rpc, _) = param
|
||||
|
||||
for {
|
||||
_ <- wallet.getBloomFilter()
|
||||
tx <- wallet.sendToAddress(junkAddress, 5.bitcoin, None)
|
||||
updatedBloom <- spv.updateBloomFilter(tx).map(_.bloomFilter)
|
||||
_ = assert(updatedBloom.contains(tx.txId))
|
||||
_ <- rpc.broadcastTransaction(tx)
|
||||
|
||||
// this should confirm our TX
|
||||
// since we updated the bloom filter
|
||||
hash <- rpc.generateToAddress(1, junkAddress).map(_.head)
|
||||
_ <- NodeTestUtil.awaitSync(spv, rpc)
|
||||
merkleBlock <- rpc.getTxOutProof(Vector(tx.txIdBE), hash)
|
||||
txs <- rpc.verifyTxOutProof(merkleBlock)
|
||||
|
||||
} yield assert(txs.contains(tx.txIdBE))
|
||||
}
|
||||
|
||||
it must "update the bloom filter with an address" in { param =>
|
||||
val SpvNodeFundedWalletBitcoind(spv, wallet, rpc, _) = param
|
||||
|
||||
for {
|
||||
_ <- wallet.getBloomFilter()
|
||||
|
||||
address <- wallet.getNewAddress()
|
||||
updatedBloom <- spv.updateBloomFilter(address).map(_.bloomFilter)
|
||||
hash <- rpc.sendToAddress(address, 1.bitcoin)
|
||||
tx <- rpc.getRawTransactionRaw(hash)
|
||||
} yield assert(updatedBloom.isRelevant(tx))
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package org.bitcoins.node.networking.peer
|
||||
|
||||
import org.bitcoins.core.currency.BitcoinsInt
|
||||
import org.bitcoins.core.p2p.TransactionMessage
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.node.{NodeCallbacks, OnTxReceived}
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.node.{
|
||||
NeutrinoNodeFundedWalletBitcoind,
|
||||
NodeTestWithCachedBitcoindNewest
|
||||
}
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.{Future, Promise}
|
||||
|
||||
class DataMessageHandlerNeutrinoNodesTest
|
||||
extends NodeTestWithCachedBitcoindNewest {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getNeutrinoWithEmbeddedDbTestConfig(pgUrl)
|
||||
|
||||
override type FixtureParam = NeutrinoNodeFundedWalletBitcoind
|
||||
|
||||
def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val outcomeF: Future[Outcome] = for {
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
outcome = withNeutrinoNodeFundedWalletBitcoind(
|
||||
test = test,
|
||||
bip39PasswordOpt = getBIP39PasswordOpt(),
|
||||
bitcoind = bitcoind
|
||||
)(system, getFreshConfig)
|
||||
f <- outcome.toFuture
|
||||
} yield f
|
||||
|
||||
new FutureOutcome(outcomeF)
|
||||
}
|
||||
|
||||
it must "verify OnTxReceived callbacks are executed" in {
|
||||
param: FixtureParam =>
|
||||
val NeutrinoNodeFundedWalletBitcoind(node, _, bitcoind, _) = param
|
||||
|
||||
val resultP: Promise[Transaction] = Promise()
|
||||
|
||||
val callback: OnTxReceived = (tx: Transaction) => {
|
||||
Future {
|
||||
resultP.success(tx)
|
||||
()
|
||||
}
|
||||
}
|
||||
val sender = node.peerMsgSenders(0)
|
||||
|
||||
for {
|
||||
|
||||
txId <- bitcoind.sendToAddress(junkAddress, 1.bitcoin)
|
||||
tx <- bitcoind.getRawTransactionRaw(txId)
|
||||
|
||||
payload = TransactionMessage(tx)
|
||||
|
||||
nodeCallbacks = NodeCallbacks.onTxReceived(callback)
|
||||
_ = node.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
|
||||
dataMessageHandler =
|
||||
DataMessageHandler(genesisChainApi, None)(node.executionContext,
|
||||
node.nodeAppConfig,
|
||||
node.chainConfig)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, node)
|
||||
result <- resultP.future
|
||||
} yield assert(result == tx)
|
||||
}
|
||||
}
|
@ -5,14 +5,14 @@ import org.bitcoins.core.currency._
|
||||
import org.bitcoins.core.gcs.{FilterType, GolombFilter}
|
||||
import org.bitcoins.core.p2p._
|
||||
import org.bitcoins.core.protocol.CompactSizeUInt
|
||||
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader, MerkleBlock}
|
||||
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader}
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.crypto.DoubleSha256Digest
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.node.NodeUnitTest
|
||||
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoindV22
|
||||
import org.bitcoins.testkit.node.fixture.NeutrinoNodeConnectedWithBitcoindV22
|
||||
import org.bitcoins.testkit.tor.CachedTor
|
||||
import org.scalatest.FutureOutcome
|
||||
|
||||
@ -22,24 +22,24 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
BitcoinSTestAppConfig.getNeutrinoWithEmbeddedDbTestConfig(pgUrl)
|
||||
|
||||
override type FixtureParam = SpvNodeConnectedWithBitcoindV22
|
||||
override type FixtureParam = NeutrinoNodeConnectedWithBitcoindV22
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome =
|
||||
withSpvNodeConnectedToBitcoindV22(test)(system, getFreshConfig)
|
||||
withNeutrinoNodeConnectedToBitcoindV22(test)(system, getFreshConfig)
|
||||
|
||||
it must "catch errors and not fail when processing an invalid payload" in {
|
||||
param: SpvNodeConnectedWithBitcoindV22 =>
|
||||
val SpvNodeConnectedWithBitcoindV22(spv, _) = param
|
||||
param: NeutrinoNodeConnectedWithBitcoindV22 =>
|
||||
val NeutrinoNodeConnectedWithBitcoindV22(node, _) = param
|
||||
|
||||
val sender = spv.peerMsgSenders(0)
|
||||
val sender = node.peerMsgSenders(0)
|
||||
for {
|
||||
chainApi <- spv.chainApiFromDb()
|
||||
chainApi <- node.chainApiFromDb()
|
||||
dataMessageHandler = DataMessageHandler(chainApi, None)(
|
||||
spv.executionContext,
|
||||
spv.nodeAppConfig,
|
||||
spv.chainConfig)
|
||||
node.executionContext,
|
||||
node.nodeAppConfig,
|
||||
node.chainConfig)
|
||||
|
||||
// Use signet genesis block header, this should be invalid for regtest
|
||||
invalidPayload =
|
||||
@ -50,50 +50,13 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
chainApi.processHeaders(invalidPayload.headers))
|
||||
|
||||
// Verify we handle the payload correctly
|
||||
_ <- dataMessageHandler.handleDataPayload(invalidPayload, sender, spv)
|
||||
_ <- dataMessageHandler.handleDataPayload(invalidPayload, sender, node)
|
||||
} yield succeed
|
||||
}
|
||||
|
||||
it must "verify OnMerkleBlock callbacks are executed" in {
|
||||
param: FixtureParam =>
|
||||
val SpvNodeConnectedWithBitcoindV22(spv, bitcoind) = param
|
||||
|
||||
val resultP: Promise[(MerkleBlock, Vector[Transaction])] = Promise()
|
||||
|
||||
val callback: OnMerkleBlockReceived = {
|
||||
(merkle: MerkleBlock, txs: Vector[Transaction]) =>
|
||||
Future {
|
||||
resultP.success((merkle, txs))
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
val sender = spv.peerMsgSenders(0)
|
||||
for {
|
||||
txId <- bitcoind.sendToAddress(junkAddress, 1.bitcoin)
|
||||
tx <- bitcoind.getRawTransactionRaw(txId)
|
||||
_ <- bitcoind.generateToAddress(blocks = 1, junkAddress)
|
||||
merkleBlock <- bitcoind.getTxOutProof(Vector(txId))
|
||||
|
||||
payload1 = MerkleBlockMessage(merkleBlock)
|
||||
payload2 = TransactionMessage(tx)
|
||||
|
||||
nodeCallbacks = NodeCallbacks(onMerkleBlockReceived = Vector(callback))
|
||||
_ = spv.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
|
||||
dataMessageHandler =
|
||||
DataMessageHandler(genesisChainApi, None)(spv.executionContext,
|
||||
spv.nodeAppConfig,
|
||||
spv.chainConfig)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload1, sender, spv)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload2, sender, spv)
|
||||
result <- resultP.future
|
||||
} yield assert(result == ((merkleBlock, Vector(tx))))
|
||||
}
|
||||
|
||||
it must "verify OnBlockReceived callbacks are executed" in {
|
||||
param: FixtureParam =>
|
||||
val SpvNodeConnectedWithBitcoindV22(spv, bitcoind) = param
|
||||
val NeutrinoNodeConnectedWithBitcoindV22(node, bitcoind) = param
|
||||
|
||||
val resultP: Promise[Block] = Promise()
|
||||
|
||||
@ -103,7 +66,7 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
()
|
||||
}
|
||||
}
|
||||
val sender = spv.peerMsgSenders(0)
|
||||
val sender = node.peerMsgSenders(0)
|
||||
|
||||
for {
|
||||
hash <- bitcoind.generateToAddress(blocks = 1, junkAddress).map(_.head)
|
||||
@ -112,20 +75,20 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
payload = BlockMessage(block)
|
||||
|
||||
nodeCallbacks = NodeCallbacks.onBlockReceived(callback)
|
||||
_ = spv.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
_ = node.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
|
||||
dataMessageHandler =
|
||||
DataMessageHandler(genesisChainApi, None)(spv.executionContext,
|
||||
spv.nodeAppConfig,
|
||||
spv.chainConfig)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, spv)
|
||||
DataMessageHandler(genesisChainApi, None)(node.executionContext,
|
||||
node.nodeAppConfig,
|
||||
node.chainConfig)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, node)
|
||||
result <- resultP.future
|
||||
} yield assert(result == block)
|
||||
}
|
||||
|
||||
it must "verify OnBlockHeadersReceived callbacks are executed" in {
|
||||
param: FixtureParam =>
|
||||
val SpvNodeConnectedWithBitcoindV22(spv, bitcoind) = param
|
||||
val NeutrinoNodeConnectedWithBitcoindV22(node, bitcoind) = param
|
||||
|
||||
val resultP: Promise[Vector[BlockHeader]] = Promise()
|
||||
|
||||
@ -138,7 +101,7 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
}
|
||||
}
|
||||
|
||||
val sender = spv.peerMsgSenders(0)
|
||||
val sender = node.peerMsgSenders(0)
|
||||
for {
|
||||
hash <- bitcoind.generateToAddress(blocks = 1, junkAddress).map(_.head)
|
||||
header <- bitcoind.getBlockHeaderRaw(hash)
|
||||
@ -147,20 +110,20 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
|
||||
callbacks = NodeCallbacks.onBlockHeadersReceived(callback)
|
||||
|
||||
_ = spv.nodeAppConfig.addCallbacks(callbacks)
|
||||
_ = node.nodeAppConfig.addCallbacks(callbacks)
|
||||
dataMessageHandler =
|
||||
DataMessageHandler(genesisChainApi, None)(spv.executionContext,
|
||||
spv.nodeAppConfig,
|
||||
spv.chainConfig)
|
||||
DataMessageHandler(genesisChainApi, None)(node.executionContext,
|
||||
node.nodeAppConfig,
|
||||
node.chainConfig)
|
||||
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, spv)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, node)
|
||||
result <- resultP.future
|
||||
} yield assert(result == Vector(header))
|
||||
}
|
||||
|
||||
it must "verify OnCompactFilterReceived callbacks are executed" in {
|
||||
param: FixtureParam =>
|
||||
val SpvNodeConnectedWithBitcoindV22(spv, bitcoind) = param
|
||||
val NeutrinoNodeConnectedWithBitcoindV22(node, bitcoind) = param
|
||||
|
||||
val resultP: Promise[Vector[(DoubleSha256Digest, GolombFilter)]] =
|
||||
Promise()
|
||||
@ -171,7 +134,7 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
()
|
||||
}
|
||||
}
|
||||
val sender = spv.peerMsgSenders(0)
|
||||
val sender = node.peerMsgSenders(0)
|
||||
for {
|
||||
hash <- bitcoind.generateToAddress(blocks = 1, junkAddress).map(_.head)
|
||||
filter <- bitcoind.getBlockFilter(hash, FilterType.Basic)
|
||||
@ -180,14 +143,47 @@ class DataMessageHandlerTest extends NodeUnitTest with CachedTor {
|
||||
CompactFilterMessage(FilterType.Basic, hash.flip, filter.filter.bytes)
|
||||
|
||||
nodeCallbacks = NodeCallbacks.onCompactFilterReceived(callback)
|
||||
_ = spv.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
_ = node.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
dataMessageHandler =
|
||||
DataMessageHandler(genesisChainApi, None)(spv.executionContext,
|
||||
spv.nodeAppConfig,
|
||||
spv.chainConfig)
|
||||
DataMessageHandler(genesisChainApi, None)(node.executionContext,
|
||||
node.nodeAppConfig,
|
||||
node.chainConfig)
|
||||
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, spv)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, node)
|
||||
result <- resultP.future
|
||||
} yield assert(result == Vector((hash.flip, filter.filter)))
|
||||
}
|
||||
|
||||
it must "verify OnTxReceived callbacks are executed" in {
|
||||
param: FixtureParam =>
|
||||
val NeutrinoNodeConnectedWithBitcoindV22(node, bitcoind) = param
|
||||
|
||||
val resultP: Promise[Transaction] = Promise()
|
||||
|
||||
val callback: OnTxReceived = (tx: Transaction) => {
|
||||
Future {
|
||||
resultP.success(tx)
|
||||
()
|
||||
}
|
||||
}
|
||||
val sender = node.peerMsgSenders(0)
|
||||
|
||||
for {
|
||||
|
||||
txId <- bitcoind.sendToAddress(junkAddress, 1.bitcoin)
|
||||
tx <- bitcoind.getRawTransactionRaw(txId)
|
||||
|
||||
payload = TransactionMessage(tx)
|
||||
|
||||
nodeCallbacks = NodeCallbacks.onTxReceived(callback)
|
||||
_ = node.nodeAppConfig.addCallbacks(nodeCallbacks)
|
||||
|
||||
dataMessageHandler =
|
||||
DataMessageHandler(genesisChainApi, None)(node.executionContext,
|
||||
node.nodeAppConfig,
|
||||
node.chainConfig)
|
||||
_ <- dataMessageHandler.handleDataPayload(payload, sender, node)
|
||||
result <- resultP.future
|
||||
} yield assert(result == tx)
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class PeerMessageHandlerTest
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
|
||||
override type FixtureParam = Peer
|
||||
|
||||
|
@ -1,115 +0,0 @@
|
||||
package org.bitcoins.node
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import org.bitcoins.asyncutil.AsyncUtil
|
||||
import org.bitcoins.chain.config.ChainAppConfig
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi.FilterResponse
|
||||
import org.bitcoins.core.api.node.NodeType
|
||||
import org.bitcoins.core.bloom.BloomFilter
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
|
||||
import org.bitcoins.core.util.Mutable
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
import org.bitcoins.node.models.Peer
|
||||
import org.bitcoins.node.networking.peer.{
|
||||
ControlMessageHandler,
|
||||
DataMessageHandler
|
||||
}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
case class SpvNode(
|
||||
dataMessageHandler: DataMessageHandler,
|
||||
nodeConfig: NodeAppConfig,
|
||||
chainConfig: ChainAppConfig,
|
||||
actorSystem: ActorSystem,
|
||||
configPeersOverride: Vector[Peer] = Vector.empty)
|
||||
extends Node {
|
||||
require(nodeConfig.nodeType == NodeType.SpvNode,
|
||||
s"We need our SPV mode enabled to be able to construct a SPV node!")
|
||||
|
||||
implicit override def system: ActorSystem = actorSystem
|
||||
|
||||
implicit override def nodeAppConfig: NodeAppConfig = nodeConfig
|
||||
|
||||
override def chainAppConfig: ChainAppConfig = chainConfig
|
||||
|
||||
private val _bloomFilter = new Mutable(BloomFilter.empty)
|
||||
|
||||
def bloomFilter: BloomFilter = _bloomFilter.atomicGet
|
||||
|
||||
val controlMessageHandler = ControlMessageHandler(this)
|
||||
|
||||
override def getDataMessageHandler: DataMessageHandler = dataMessageHandler
|
||||
|
||||
override val peerManager: PeerManager = PeerManager(this, configPeersOverride)
|
||||
|
||||
def setBloomFilter(bloom: BloomFilter): SpvNode = {
|
||||
_bloomFilter.atomicSet(bloom)
|
||||
this
|
||||
}
|
||||
|
||||
override def updateDataMessageHandler(
|
||||
dataMessageHandler: DataMessageHandler): SpvNode = {
|
||||
copy(dataMessageHandler = dataMessageHandler)
|
||||
}
|
||||
|
||||
/** Updates our bloom filter to match the given TX
|
||||
*
|
||||
* @return SPV node with the updated bloom filter
|
||||
*/
|
||||
def updateBloomFilter(transaction: Transaction): Future[SpvNode] = {
|
||||
logger.info(s"Updating bloom filter with transaction=${transaction.txIdBE}")
|
||||
val newBloom = _bloomFilter.atomicUpdate(transaction)(_.update(_))
|
||||
|
||||
// we could send filteradd messages, but we would
|
||||
// then need to calculate all the new elements in
|
||||
// the filter. this is easier:-)
|
||||
for {
|
||||
_ <- peerMsgSenders(0).sendFilterClearMessage()
|
||||
_ <- peerMsgSenders(0).sendFilterLoadMessage(newBloom)
|
||||
} yield this
|
||||
|
||||
}
|
||||
|
||||
/** Updates our bloom filter to match the given address
|
||||
*
|
||||
* @return SPV node with the updated bloom filter
|
||||
*/
|
||||
def updateBloomFilter(address: BitcoinAddress): Future[SpvNode] = {
|
||||
logger.info(s"Updating bloom filter with address=$address")
|
||||
val hash = address.hash
|
||||
_bloomFilter.atomicUpdate(hash)(_.insert(_))
|
||||
|
||||
val sentFilterAddF = peerMsgSenders(0).sendFilterAddMessage(hash)
|
||||
|
||||
sentFilterAddF.map(_ => this)
|
||||
}
|
||||
|
||||
override def start(): Future[SpvNode] = {
|
||||
for {
|
||||
node <- super.start()
|
||||
_ <- AsyncUtil.retryUntilSatisfiedF(() => isConnected(0))
|
||||
_ <- peerMsgSenders(0).sendFilterLoadMessage(bloomFilter)
|
||||
} yield {
|
||||
logger.info(
|
||||
s"Sending bloomfilter=${bloomFilter.hex} to ${peerManager.peers(0)}")
|
||||
node.asInstanceOf[SpvNode]
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the block height of the given block stamp */
|
||||
override def getHeightByBlockStamp(blockStamp: BlockStamp): Future[Int] =
|
||||
chainApiFromDb().flatMap(_.getHeightByBlockStamp(blockStamp))
|
||||
|
||||
private val cfErrMsg = "Compact filters are not supported in SPV mode"
|
||||
|
||||
/** Gets the number of compact filters in the database */
|
||||
override def getFilterCount(): Future[Int] =
|
||||
Future.failed(new RuntimeException(cfErrMsg))
|
||||
|
||||
override def getFiltersBetweenHeights(
|
||||
startHeight: Int,
|
||||
endHeight: Int): Future[Vector[FilterResponse]] =
|
||||
Future.failed(new RuntimeException(cfErrMsg))
|
||||
}
|
@ -72,7 +72,7 @@ case class NodeAppConfig(baseDatadir: Path, configOverrides: Vector[Config])(
|
||||
case None =>
|
||||
Future.unit
|
||||
}
|
||||
case NodeType.SpvNode | NodeType.NeutrinoNode | NodeType.FullNode =>
|
||||
case NodeType.NeutrinoNode | NodeType.FullNode =>
|
||||
Future.unit
|
||||
}
|
||||
}
|
||||
@ -170,13 +170,6 @@ object NodeAppConfig extends AppConfigFactoryActorSystem[NodeAppConfig] {
|
||||
.map(handler => DataMessageHandler(handler, walletCreationTimeOpt))
|
||||
|
||||
nodeConf.nodeType match {
|
||||
case NodeType.SpvNode =>
|
||||
dmhF.map(dmh =>
|
||||
SpvNode(dmh,
|
||||
nodeConf,
|
||||
chainConf,
|
||||
system,
|
||||
configPeersOverride = peers))
|
||||
case NodeType.NeutrinoNode =>
|
||||
dmhF.map(dmh =>
|
||||
NeutrinoNode(dmh,
|
||||
|
@ -92,8 +92,6 @@ case class ControlMessageHandler(node: Node)(implicit ec: ExecutionContext)
|
||||
throw new Exception("Node cannot be FullNode")
|
||||
case NodeType.NeutrinoNode =>
|
||||
node.peerManager.createInDb(peer).map(_ => ())
|
||||
case NodeType.SpvNode =>
|
||||
node.peerManager.createInDb(peer).map(_ => ())
|
||||
}
|
||||
case nodeType: ExternalImplementationNodeType =>
|
||||
nodeType match {
|
||||
|
@ -207,12 +207,6 @@ case class DataMessageHandler(
|
||||
s"Received headers=${headers.map(_.hashBE.hex).mkString("[", ",", "]")}")
|
||||
val chainApiF = chainApi.processHeaders(headers)
|
||||
|
||||
if (appConfig.nodeType == NodeType.SpvNode) {
|
||||
logger.trace(s"Requesting data for headers=${headers.length}")
|
||||
peerMsgSender.sendGetDataMessage(TypeIdentifier.MsgFilteredBlock,
|
||||
headers.map(_.hash): _*)
|
||||
}
|
||||
|
||||
val getHeadersF = chainApiF
|
||||
.flatMap { newApi =>
|
||||
if (headers.nonEmpty) {
|
||||
@ -399,10 +393,7 @@ case class DataMessageHandler(
|
||||
logger.debug(s"Received inv=${invMsg}")
|
||||
val getData = GetDataMessage(invMsg.inventories.flatMap {
|
||||
case Inventory(TypeIdentifier.MsgBlock, hash) =>
|
||||
// only request the merkle block if we are spv enabled
|
||||
appConfig.nodeType match {
|
||||
case NodeType.SpvNode =>
|
||||
Some(Inventory(TypeIdentifier.MsgFilteredBlock, hash))
|
||||
case NodeType.NeutrinoNode | NodeType.FullNode =>
|
||||
if (syncing) None
|
||||
else Some(Inventory(TypeIdentifier.MsgWitnessBlock, hash))
|
||||
|
@ -33,55 +33,6 @@ object BitcoinSTestAppConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/** App configuration suitable for test purposes:
|
||||
*
|
||||
* 1) Data directory is set to user temp directory
|
||||
* 2) Logging is turned down to WARN
|
||||
*/
|
||||
def getSpvTestConfig(config: Config*)(implicit
|
||||
system: ActorSystem): BitcoinSAppConfig = {
|
||||
val overrideConf = ConfigFactory.parseString {
|
||||
s"""
|
||||
|bitcoin-s {
|
||||
| node {
|
||||
| mode = spv
|
||||
| }
|
||||
| wallet {
|
||||
| allowExternalDLCAddresses = true
|
||||
| }
|
||||
| proxy.enabled = $torEnabled
|
||||
| tor.enabled = $torEnabled
|
||||
| tor.use-random-ports = false
|
||||
|}
|
||||
""".stripMargin
|
||||
}
|
||||
BitcoinSAppConfig(tmpDir(), (overrideConf +: config).toVector)
|
||||
}
|
||||
|
||||
def getSpvWithEmbeddedDbTestConfig(
|
||||
pgUrl: () => Option[String],
|
||||
config: Vector[Config])(implicit
|
||||
system: ActorSystem): BitcoinSAppConfig = {
|
||||
val overrideConf = ConfigFactory
|
||||
.parseString {
|
||||
s"""
|
||||
|bitcoin-s {
|
||||
| node {
|
||||
| mode = spv
|
||||
| }
|
||||
| proxy.enabled = $torEnabled
|
||||
| tor.enabled = $torEnabled
|
||||
| tor.use-random-ports = false
|
||||
|}
|
||||
""".stripMargin
|
||||
}
|
||||
.withFallback(genWalletNameConf)
|
||||
|
||||
BitcoinSAppConfig(
|
||||
tmpDir(),
|
||||
(overrideConf +: configWithEmbeddedDb(project = None, pgUrl) +: config))
|
||||
}
|
||||
|
||||
def getNeutrinoTestConfig(config: Config*)(implicit
|
||||
system: ActorSystem): BitcoinSAppConfig = {
|
||||
val overrideConf = ConfigFactory.parseString {
|
||||
@ -91,7 +42,9 @@ object BitcoinSTestAppConfig {
|
||||
| mode = neutrino
|
||||
| relay = true
|
||||
| }
|
||||
|
|
||||
| wallet {
|
||||
| allowExternalDLCAddresses = true
|
||||
| }
|
||||
| proxy.enabled = $torEnabled
|
||||
| tor.enabled = $torEnabled
|
||||
| tor.use-random-ports = false
|
||||
|
@ -11,7 +11,7 @@ trait ChainDbUnitTest extends ChainUnitTest with EmbeddedPg {
|
||||
val memoryDb =
|
||||
BitcoinSTestAppConfig.configWithEmbeddedDb(Some(ProjectType.Chain), pgUrl)
|
||||
val chainConfig: ChainAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig().chainConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig().chainConf
|
||||
chainConfig.withOverrides(memoryDb)
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ trait ChainDbUnitTest extends ChainUnitTest with EmbeddedPg {
|
||||
BitcoinSTestAppConfig.configWithEmbeddedDb(Some(ProjectType.Chain), pgUrl)
|
||||
val mainnetConf = ConfigFactory.parseString("bitcoin-s.network = mainnet")
|
||||
val chainConfig: ChainAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig(mainnetConf).chainConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig(mainnetConf).chainConf
|
||||
chainConfig.withOverrides(memoryDb)
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ trait ChainUnitTest
|
||||
*/
|
||||
lazy val mainnetAppConfig: ChainAppConfig = {
|
||||
val mainnetConf = ConfigFactory.parseString("bitcoin-s.network = mainnet")
|
||||
BitcoinSTestAppConfig.getSpvTestConfig(mainnetConf).chainConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig(mainnetConf).chainConf
|
||||
}
|
||||
|
||||
override def beforeAll(): Unit = {
|
||||
|
@ -17,7 +17,7 @@ trait NodeDAOFixture extends NodeUnitTest with CachedBitcoinSAppConfig {
|
||||
|
||||
/** Wallet config with data directory set to user temp directory */
|
||||
override protected def getFreshConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, Vector.empty)
|
||||
BitcoinSTestAppConfig.getNeutrinoWithEmbeddedDbTestConfig(pgUrl)
|
||||
|
||||
private lazy val daos = {
|
||||
val tx = BroadcastAbleTransactionDAO()
|
||||
|
@ -47,7 +47,7 @@ trait CachedChainAppConfig {
|
||||
_: BitcoinSAkkaAsyncTest =>
|
||||
|
||||
private[this] lazy val cachedConfig: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
|
||||
implicit protected lazy val cachedChainConf: ChainAppConfig = {
|
||||
cachedConfig.chainConf
|
||||
|
@ -1,11 +1,10 @@
|
||||
package org.bitcoins.testkit.node
|
||||
|
||||
import org.bitcoins.node.{NeutrinoNode, Node, SpvNode}
|
||||
import org.bitcoins.node.{NeutrinoNode, Node}
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.testkit.node.fixture.{
|
||||
NeutrinoNodeConnectedWithBitcoind,
|
||||
NodeConnectedWithBitcoind,
|
||||
SpvNodeConnectedWithBitcoind
|
||||
NodeConnectedWithBitcoind
|
||||
}
|
||||
import org.bitcoins.wallet.Wallet
|
||||
|
||||
@ -13,7 +12,7 @@ import org.bitcoins.wallet.Wallet
|
||||
* 1. a funded bitcoind wallet
|
||||
* 2. a funded bitcoin-s wallet
|
||||
* 3. a chain handler with the appropriate tables created
|
||||
* 4. a spv node that is connected to the bitcoin instance -- but not started!
|
||||
* 4. a neutrino node that is connected to the bitcoin instance -- but not started!
|
||||
*/
|
||||
trait NodeFundedWalletBitcoind {
|
||||
def node: Node
|
||||
@ -25,18 +24,6 @@ trait NodeFundedWalletBitcoind {
|
||||
def toNodeConnectedWithBitcoind: NodeConnectedWithBitcoind
|
||||
}
|
||||
|
||||
case class SpvNodeFundedWalletBitcoind(
|
||||
node: SpvNode,
|
||||
wallet: Wallet,
|
||||
bitcoindRpc: BitcoindRpcClient,
|
||||
bip39PasswordOpt: Option[String])
|
||||
extends NodeFundedWalletBitcoind {
|
||||
|
||||
override def toNodeConnectedWithBitcoind: SpvNodeConnectedWithBitcoind = {
|
||||
SpvNodeConnectedWithBitcoind(node, bitcoindRpc)
|
||||
}
|
||||
}
|
||||
|
||||
case class NeutrinoNodeFundedWalletBitcoind(
|
||||
node: NeutrinoNode,
|
||||
wallet: Wallet,
|
||||
|
@ -5,14 +5,11 @@ import org.bitcoins.core.api.node.NodeType
|
||||
import org.bitcoins.node.Node
|
||||
import org.bitcoins.node.models.Peer
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.node.NodeUnitTest.{createPeer, syncNeutrinoNode}
|
||||
import org.bitcoins.testkit.node.fixture.{
|
||||
NeutrinoNodeConnectedWithBitcoind,
|
||||
NeutrinoNodeConnectedWithBitcoinds,
|
||||
SpvNodeConnectedWithBitcoind,
|
||||
SpvNodeConnectedWithBitcoindV19
|
||||
NeutrinoNodeConnectedWithBitcoinds
|
||||
}
|
||||
import org.bitcoins.testkit.rpc.{
|
||||
CachedBitcoind,
|
||||
@ -34,48 +31,27 @@ import scala.concurrent.Future
|
||||
trait NodeTestWithCachedBitcoind extends BaseNodeTest with CachedTor {
|
||||
_: CachedBitcoind[_] =>
|
||||
|
||||
def withSpvNodeFundedWalletBitcoindCached(
|
||||
test: OneArgAsyncTest,
|
||||
bip39PasswordOpt: Option[String],
|
||||
bitcoind: BitcoindRpcClient)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
|
||||
makeDependentFixture[SpvNodeFundedWalletBitcoind](
|
||||
build = () =>
|
||||
NodeUnitTest.createSpvNodeFundedWalletFromBitcoind(
|
||||
walletCallbacks = WalletCallbacks.empty,
|
||||
bip39PasswordOpt = bip39PasswordOpt,
|
||||
bitcoind = bitcoind)(
|
||||
system, // Force V18 because Spv is disabled on versions after
|
||||
appConfig),
|
||||
{ x: SpvNodeFundedWalletBitcoind =>
|
||||
tearDownNodeWithBitcoind(x)
|
||||
}
|
||||
)(test)
|
||||
}
|
||||
|
||||
def withSpvNodeConnectedToBitcoindCached(
|
||||
def withNeutrinoNodeConnectedToBitcoindCached(
|
||||
test: OneArgAsyncTest,
|
||||
bitcoind: BitcoindRpcClient)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
val nodeWithBitcoindBuilder: () => Future[SpvNodeConnectedWithBitcoind] = {
|
||||
() =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
for {
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- NodeUnitTest.createSpvNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
started <- node.start()
|
||||
_ <- NodeUnitTest.syncSpvNode(started, bitcoind)
|
||||
} yield SpvNodeConnectedWithBitcoind(node, bitcoind)
|
||||
val nodeWithBitcoindBuilder: () => Future[
|
||||
NeutrinoNodeConnectedWithBitcoind] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.NeutrinoNode)
|
||||
for {
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- NodeUnitTest.createNeutrinoNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
started <- node.start()
|
||||
_ <- NodeUnitTest.syncNeutrinoNode(started, bitcoind)
|
||||
} yield NeutrinoNodeConnectedWithBitcoind(node, bitcoind)
|
||||
}
|
||||
|
||||
makeDependentFixture[SpvNodeConnectedWithBitcoind](
|
||||
makeDependentFixture[NeutrinoNodeConnectedWithBitcoind](
|
||||
build = nodeWithBitcoindBuilder,
|
||||
{ x: SpvNodeConnectedWithBitcoind =>
|
||||
{ x: NeutrinoNodeConnectedWithBitcoind =>
|
||||
NodeUnitTest.destroyNode(x.node)
|
||||
})(test)
|
||||
}
|
||||
@ -205,32 +181,6 @@ trait NodeTestWithCachedBitcoindV19
|
||||
extends NodeTestWithCachedBitcoind
|
||||
with CachedBitcoindV19 {
|
||||
|
||||
def withSpvNodeConnectedToBitcoindV19Cached(
|
||||
test: OneArgAsyncTest,
|
||||
bitcoind: BitcoindV19RpcClient)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
val nodeWithBitcoindBuilder: () => Future[
|
||||
SpvNodeConnectedWithBitcoindV19] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
for {
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- NodeUnitTest.createSpvNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
started <- node.start()
|
||||
_ <- NodeUnitTest.syncSpvNode(started, bitcoind)
|
||||
} yield SpvNodeConnectedWithBitcoindV19(node, bitcoind)
|
||||
}
|
||||
|
||||
makeDependentFixture[SpvNodeConnectedWithBitcoindV19](
|
||||
build = nodeWithBitcoindBuilder,
|
||||
{ x: SpvNodeConnectedWithBitcoindV19 =>
|
||||
NodeUnitTest.destroyNode(x.node)
|
||||
}
|
||||
)(test)
|
||||
}
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
super[CachedBitcoindV19].afterAll()
|
||||
super[NodeTestWithCachedBitcoind].afterAll()
|
||||
|
@ -10,22 +10,17 @@ import org.bitcoins.node._
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
import org.bitcoins.node.models.Peer
|
||||
import org.bitcoins.node.networking.peer._
|
||||
import org.bitcoins.rpc.client.common.BitcoindVersion.{V18, V21, V22}
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.client.v21.BitcoindV21RpcClient
|
||||
import org.bitcoins.rpc.client.common.BitcoindVersion.V22
|
||||
import org.bitcoins.rpc.client.v22.BitcoindV22RpcClient
|
||||
import org.bitcoins.testkit.node.NodeUnitTest.createPeer
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.chain.ChainUnitTest
|
||||
import org.bitcoins.testkit.fixtures.BitcoinSFixture
|
||||
import org.bitcoins.testkit.node.NodeUnitTest.{
|
||||
createPeer,
|
||||
emptyPeer,
|
||||
syncNeutrinoNode
|
||||
}
|
||||
import org.bitcoins.testkit.node.NodeUnitTest.{emptyPeer, syncNeutrinoNode}
|
||||
import org.bitcoins.testkit.node.fixture._
|
||||
import org.bitcoins.testkit.wallet.{BitcoinSWalletTest, WalletWithBitcoindRpc}
|
||||
import org.bitcoins.testkitcore.node.P2PMessageTestUtil
|
||||
import org.bitcoins.wallet.WalletCallbacks
|
||||
import org.scalatest.FutureOutcome
|
||||
|
||||
@ -35,16 +30,17 @@ import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
trait NodeUnitTest extends BaseNodeTest {
|
||||
|
||||
def withDisconnectedSpvNode(test: OneArgAsyncTest)(implicit
|
||||
def withDisconnectedNeutrinoNode(test: OneArgAsyncTest)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
|
||||
val nodeBuilder: () => Future[SpvNode] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
val nodeBuilder: () => Future[NeutrinoNode] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.NeutrinoNode)
|
||||
for {
|
||||
node <- NodeUnitTest.createSpvNode(emptyPeer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
node <- NodeUnitTest.createNeutrinoNode(emptyPeer, None)(
|
||||
system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
//we aren't calling node.start(), but we need to call appConfig.start()
|
||||
//to make sure migrations are run
|
||||
_ <- node.chainConfig.start()
|
||||
@ -64,77 +60,24 @@ trait NodeUnitTest extends BaseNodeTest {
|
||||
)(test)
|
||||
}
|
||||
|
||||
def withSpvNodeConnectedToBitcoind(
|
||||
test: OneArgAsyncTest,
|
||||
versionOpt: Option[BitcoindVersion] = None)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
val nodeWithBitcoindBuilder: () => Future[SpvNodeConnectedWithBitcoind] = {
|
||||
() =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
for {
|
||||
bitcoind <- BitcoinSFixture.createBitcoind(versionOpt)
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- NodeUnitTest.createSpvNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
started <- node.start()
|
||||
_ <- NodeUnitTest.syncSpvNode(started, bitcoind)
|
||||
} yield SpvNodeConnectedWithBitcoind(node, bitcoind)
|
||||
}
|
||||
|
||||
makeDependentFixture(
|
||||
build = nodeWithBitcoindBuilder,
|
||||
destroy = NodeUnitTest.destroyNodeConnectedWithBitcoind(
|
||||
_: NodeConnectedWithBitcoind)(system, appConfig)
|
||||
)(test)
|
||||
}
|
||||
|
||||
def withSpvNodeConnectedToBitcoindV21(test: OneArgAsyncTest)(implicit
|
||||
def withNeutrinoNodeConnectedToBitcoindV22(test: OneArgAsyncTest)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
val nodeWithBitcoindBuilder: () => Future[
|
||||
SpvNodeConnectedWithBitcoindV21] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
for {
|
||||
bitcoind <-
|
||||
BitcoinSFixture
|
||||
.createBitcoindWithFunds(Some(V21))
|
||||
.map(_.asInstanceOf[BitcoindV21RpcClient])
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- NodeUnitTest.createSpvNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
started <- node.start()
|
||||
_ <- NodeUnitTest.syncSpvNode(started, bitcoind)
|
||||
} yield SpvNodeConnectedWithBitcoindV21(node, bitcoind)
|
||||
}
|
||||
|
||||
makeDependentFixture(
|
||||
build = nodeWithBitcoindBuilder,
|
||||
destroy = NodeUnitTest.destroyNodeConnectedWithBitcoind(
|
||||
_: NodeConnectedWithBitcoind)(system, appConfig)
|
||||
)(test)
|
||||
}
|
||||
|
||||
def withSpvNodeConnectedToBitcoindV22(test: OneArgAsyncTest)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
val nodeWithBitcoindBuilder: () => Future[
|
||||
SpvNodeConnectedWithBitcoindV22] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
NeutrinoNodeConnectedWithBitcoindV22] = { () =>
|
||||
require(appConfig.nodeConf.nodeType == NodeType.NeutrinoNode)
|
||||
for {
|
||||
bitcoind <-
|
||||
BitcoinSFixture
|
||||
.createBitcoindWithFunds(Some(V22))
|
||||
.map(_.asInstanceOf[BitcoindV22RpcClient])
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- NodeUnitTest.createSpvNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
node <- NodeUnitTest.createNeutrinoNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
started <- node.start()
|
||||
_ <- NodeUnitTest.syncSpvNode(started, bitcoind)
|
||||
} yield SpvNodeConnectedWithBitcoindV22(node, bitcoind)
|
||||
_ <- NodeUnitTest.syncNeutrinoNode(started, bitcoind)
|
||||
} yield NeutrinoNodeConnectedWithBitcoindV22(node, bitcoind)
|
||||
}
|
||||
|
||||
makeDependentFixture(
|
||||
@ -170,26 +113,6 @@ trait NodeUnitTest extends BaseNodeTest {
|
||||
)(test)
|
||||
}
|
||||
|
||||
def withSpvNodeFundedWalletBitcoind(
|
||||
test: OneArgAsyncTest,
|
||||
bip39PasswordOpt: Option[String])(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): FutureOutcome = {
|
||||
|
||||
makeDependentFixture(
|
||||
build = () =>
|
||||
NodeUnitTest.createSpvNodeFundedWalletBitcoind(bip39PasswordOpt =
|
||||
bip39PasswordOpt,
|
||||
versionOpt = Option(V18),
|
||||
walletCallbacks =
|
||||
WalletCallbacks.empty)(
|
||||
system, // Force V18 because Spv is disabled on versions after
|
||||
appConfig),
|
||||
destroy = NodeUnitTest.destroyNodeFundedWalletBitcoind(
|
||||
_: NodeFundedWalletBitcoind)(system, appConfig)
|
||||
)(test)
|
||||
}
|
||||
|
||||
def withNeutrinoNodeFundedWalletBitcoind(
|
||||
test: OneArgAsyncTest,
|
||||
bip39PasswordOpt: Option[String],
|
||||
@ -324,66 +247,6 @@ object NodeUnitTest extends P2PLogger {
|
||||
resultF
|
||||
}
|
||||
|
||||
/** Creates a spv node, a funded bitcoin-s wallet, all of which are connected to bitcoind */
|
||||
def createSpvNodeFundedWalletBitcoind(
|
||||
walletCallbacks: WalletCallbacks,
|
||||
bip39PasswordOpt: Option[String],
|
||||
versionOpt: Option[BitcoindVersion] = None)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): Future[SpvNodeFundedWalletBitcoind] = {
|
||||
import system.dispatcher
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
for {
|
||||
bitcoind <- BitcoinSFixture.createBitcoindWithFunds(versionOpt)
|
||||
spvNodeWithBitcoind <- createSpvNodeFundedWalletFromBitcoind(
|
||||
walletCallbacks,
|
||||
bip39PasswordOpt,
|
||||
bitcoind)
|
||||
} yield {
|
||||
spvNodeWithBitcoind
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a spv node & funded wallet with the given bitcoind */
|
||||
def createSpvNodeFundedWalletFromBitcoind(
|
||||
walletCallbacks: WalletCallbacks,
|
||||
bip39PasswordOpt: Option[String],
|
||||
bitcoind: BitcoindRpcClient)(implicit
|
||||
system: ActorSystem,
|
||||
appConfig: BitcoinSAppConfig): Future[SpvNodeFundedWalletBitcoind] = {
|
||||
import system.dispatcher
|
||||
require(appConfig.nodeConf.nodeType == NodeType.SpvNode)
|
||||
for {
|
||||
peer <- createPeer(bitcoind)
|
||||
node <- createSpvNode(peer, None)(system,
|
||||
appConfig.chainConf,
|
||||
appConfig.nodeConf)
|
||||
fundedWallet <- BitcoinSWalletTest.fundedWalletAndBitcoind(
|
||||
bitcoindRpcClient = bitcoind,
|
||||
nodeApi = node,
|
||||
chainQueryApi = bitcoind,
|
||||
bip39PasswordOpt = bip39PasswordOpt,
|
||||
walletCallbacks = walletCallbacks)
|
||||
spvCallbacks =
|
||||
BitcoinSWalletTest.createSpvNodeCallbacksForWallet(fundedWallet.wallet)
|
||||
_ = appConfig.nodeConf.addCallbacks(spvCallbacks)
|
||||
walletBloomFilter <- fundedWallet.wallet.getBloomFilter()
|
||||
withBloomFilter = node.setBloomFilter(walletBloomFilter)
|
||||
startedNodeWithBloomFilter <- withBloomFilter.start()
|
||||
_ <- syncSpvNode(startedNodeWithBloomFilter, bitcoind)
|
||||
//callbacks are executed asynchronously, which is how we fund the wallet
|
||||
//so we need to wait until the wallet balances are correct
|
||||
_ <- BitcoinSWalletTest.awaitWalletBalances(fundedWallet)(
|
||||
appConfig.walletConf,
|
||||
system)
|
||||
} yield {
|
||||
SpvNodeFundedWalletBitcoind(node = startedNodeWithBloomFilter,
|
||||
wallet = fundedWallet.wallet,
|
||||
bitcoindRpc = fundedWallet.bitcoind,
|
||||
bip39PasswordOpt)
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a neutrino node, a funded bitcoin-s wallet, all of which are connected to bitcoind */
|
||||
def createNeutrinoNodeFundedWalletBitcoind(
|
||||
bip39PasswordOpt: Option[String],
|
||||
@ -505,37 +368,8 @@ object NodeUnitTest extends P2PLogger {
|
||||
Peer(id = None, socket = socket, socks5ProxyParams = None)
|
||||
}
|
||||
|
||||
/** Creates a spv node peered with the given bitcoind client
|
||||
* This does NOT start the spv node
|
||||
*/
|
||||
def createSpvNode(peer: Peer, walletCreationTimeOpt: Option[Instant])(implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig,
|
||||
nodeAppConfig: NodeAppConfig): Future[SpvNode] = {
|
||||
import system.dispatcher
|
||||
|
||||
val checkConfigF = Future {
|
||||
assert(nodeAppConfig.nodeType == NodeType.SpvNode)
|
||||
}
|
||||
|
||||
for {
|
||||
_ <- checkConfigF
|
||||
_ <- nodeAppConfig.start()
|
||||
chainHandler <- ChainUnitTest.createChainHandler()
|
||||
} yield {
|
||||
val dmh = DataMessageHandler(chainHandler, walletCreationTimeOpt)
|
||||
SpvNode(
|
||||
configPeersOverride = Vector(peer),
|
||||
dataMessageHandler = dmh,
|
||||
nodeConfig = nodeAppConfig,
|
||||
chainConfig = chainAppConfig,
|
||||
actorSystem = system
|
||||
).setBloomFilter(P2PMessageTestUtil.emptyBloomFilter)
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a Neutrino node peered with the given bitcoind client, this method
|
||||
* also calls [[org.bitcoins.node.Node.start() start]] to start the node
|
||||
/** Creates a Neutrino node peered with the given bitcoind client, this does NOT
|
||||
* start the neutrino node
|
||||
*/
|
||||
def createNeutrinoNode(
|
||||
bitcoind: BitcoindRpcClient,
|
||||
@ -568,8 +402,40 @@ object NodeUnitTest extends P2PLogger {
|
||||
nodeF
|
||||
}
|
||||
|
||||
/** Creates a Neutrino node peered with the given bitcoind client, this method
|
||||
* also calls [[org.bitcoins.node.Node.start() start]] to start the node
|
||||
/** Creates a Neutrino node peered with the given peer, this does NOT
|
||||
* start the neutrino node
|
||||
*/
|
||||
def createNeutrinoNode(peer: Peer, walletCreationTimeOpt: Option[Instant])(
|
||||
implicit
|
||||
system: ActorSystem,
|
||||
chainAppConfig: ChainAppConfig,
|
||||
nodeAppConfig: NodeAppConfig): Future[NeutrinoNode] = {
|
||||
import system.dispatcher
|
||||
|
||||
val checkConfigF = Future {
|
||||
assert(nodeAppConfig.nodeType == NodeType.NeutrinoNode)
|
||||
}
|
||||
val chainApiF = for {
|
||||
_ <- checkConfigF
|
||||
chainHandler <- ChainUnitTest.createChainHandler()
|
||||
} yield chainHandler
|
||||
val nodeF = for {
|
||||
_ <- nodeAppConfig.start()
|
||||
chainApi <- chainApiF
|
||||
} yield {
|
||||
val dmh = DataMessageHandler(chainApi, walletCreationTimeOpt)
|
||||
NeutrinoNode(configPeersOverride = Vector(peer),
|
||||
dataMessageHandler = dmh,
|
||||
nodeConfig = nodeAppConfig,
|
||||
chainConfig = chainAppConfig,
|
||||
actorSystem = system)
|
||||
}
|
||||
|
||||
nodeF
|
||||
}
|
||||
|
||||
/** Creates a Neutrino node peered with the given bitcoind client, this does NOT
|
||||
* start the neutrino node
|
||||
*/
|
||||
def createNeutrinoNode(
|
||||
bitcoinds: Vector[BitcoindRpcClient],
|
||||
@ -615,15 +481,6 @@ object NodeUnitTest extends P2PLogger {
|
||||
} yield node
|
||||
}
|
||||
|
||||
def syncSpvNode(node: SpvNode, bitcoind: BitcoindRpcClient)(implicit
|
||||
system: ActorSystem): Future[SpvNode] = {
|
||||
import system.dispatcher
|
||||
for {
|
||||
_ <- node.sync()
|
||||
_ <- NodeTestUtil.awaitSync(node, bitcoind)
|
||||
} yield node
|
||||
}
|
||||
|
||||
/** This is needed for postgres, we do not drop tables in between individual tests with postgres
|
||||
* rather an entire test suite shares the same postgres database.
|
||||
* therefore, we need to clean the database after each test, so that migrations can be applied during
|
||||
|
@ -1,37 +1,15 @@
|
||||
package org.bitcoins.testkit.node.fixture
|
||||
|
||||
import org.bitcoins.node.{NeutrinoNode, Node, SpvNode}
|
||||
import org.bitcoins.node.{NeutrinoNode, Node}
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
|
||||
import org.bitcoins.rpc.client.v21.BitcoindV21RpcClient
|
||||
import org.bitcoins.rpc.client.v22.BitcoindV22RpcClient
|
||||
|
||||
/** Gives us a fixture that has a SPV node connected with the bitcoind instance */
|
||||
/** Gives us a fixture that has a Neutrino node connected with the bitcoind instance */
|
||||
trait NodeConnectedWithBitcoind {
|
||||
def node: Node
|
||||
def bitcoind: BitcoindRpcClient
|
||||
}
|
||||
|
||||
case class SpvNodeConnectedWithBitcoind(
|
||||
node: SpvNode,
|
||||
bitcoind: BitcoindRpcClient)
|
||||
extends NodeConnectedWithBitcoind
|
||||
|
||||
case class SpvNodeConnectedWithBitcoindV22(
|
||||
node: SpvNode,
|
||||
bitcoind: BitcoindV22RpcClient)
|
||||
extends NodeConnectedWithBitcoind
|
||||
|
||||
case class SpvNodeConnectedWithBitcoindV21(
|
||||
node: SpvNode,
|
||||
bitcoind: BitcoindV21RpcClient)
|
||||
extends NodeConnectedWithBitcoind
|
||||
|
||||
case class SpvNodeConnectedWithBitcoindV19(
|
||||
node: SpvNode,
|
||||
bitcoind: BitcoindV19RpcClient)
|
||||
extends NodeConnectedWithBitcoind
|
||||
|
||||
case class NeutrinoNodeConnectedWithBitcoind(
|
||||
node: NeutrinoNode,
|
||||
bitcoind: BitcoindRpcClient)
|
||||
@ -46,3 +24,8 @@ case class NeutrinoNodeConnectedWithBitcoinds(
|
||||
node: NeutrinoNode,
|
||||
bitcoinds: Vector[BitcoindRpcClient]
|
||||
) extends NodeConnectedWithBitcoinds
|
||||
|
||||
case class NeutrinoNodeConnectedWithBitcoindV22(
|
||||
node: NeutrinoNode,
|
||||
bitcoind: BitcoindV22RpcClient)
|
||||
extends NodeConnectedWithBitcoind
|
||||
|
@ -16,7 +16,7 @@ trait CachedTor {
|
||||
_: BitcoinSAkkaAsyncTest =>
|
||||
|
||||
implicit protected lazy val torConfig: TorAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig().torConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig().torConf
|
||||
|
||||
protected val isTorStarted: AtomicBoolean = new AtomicBoolean(false)
|
||||
|
||||
|
@ -141,7 +141,7 @@ object BaseWalletTest {
|
||||
|
||||
def getFreshConfig(pgUrl: () => Option[String], config: Vector[Config])(
|
||||
implicit system: ActorSystem): BitcoinSAppConfig = {
|
||||
BitcoinSTestAppConfig.getSpvWithEmbeddedDbTestConfig(pgUrl, config)
|
||||
BitcoinSTestAppConfig.getNeutrinoWithEmbeddedDbTestConfig(pgUrl, config: _*)
|
||||
}
|
||||
|
||||
def getFreshWalletAppConfig(
|
||||
|
@ -21,7 +21,7 @@ trait BitcoinSDualWalletTest extends BitcoinSWalletTest {
|
||||
import BitcoinSWalletTest._
|
||||
|
||||
implicit protected def config2: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
|
||||
implicit protected def wallet2AppConfig: WalletAppConfig = {
|
||||
config2.walletConf
|
||||
|
@ -16,7 +16,7 @@ import org.bitcoins.core.wallet.fee._
|
||||
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
||||
import org.bitcoins.dlc.wallet.{DLCAppConfig, DLCWallet}
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
import org.bitcoins.node.{NodeCallbacks, OnMerkleBlockReceived}
|
||||
import org.bitcoins.node.NodeCallbacks
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
@ -699,19 +699,6 @@ object BitcoinSWalletTest extends WalletLogger {
|
||||
CallbackUtil.createNeutrinoNodeCallbacksForWallet(wallet)
|
||||
}
|
||||
|
||||
/** Registers a callback to handle merkle blocks given to us by a spv node */
|
||||
def createSpvNodeCallbacksForWallet(wallet: Wallet)(implicit
|
||||
ec: ExecutionContext): NodeCallbacks = {
|
||||
val onMerkleBlockReceived: OnMerkleBlockReceived = {
|
||||
case (merkleBlock, txs) =>
|
||||
for {
|
||||
_ <- wallet.processTransactions(txs,
|
||||
Some(merkleBlock.blockHeader.hashBE))
|
||||
} yield ()
|
||||
}
|
||||
NodeCallbacks(onMerkleBlockReceived = Vector(onMerkleBlockReceived))
|
||||
}
|
||||
|
||||
/** Makes sure our wallet is fully funded with the default amounts specified in
|
||||
* [[BitcoinSWalletTest]]. This will future won't be completed until balances satisfy [[isSameWalletBalances()]]
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@ trait DualWalletTestCachedBitcoind
|
||||
import BitcoinSWalletTest._
|
||||
|
||||
implicit protected def config2: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig()
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||
|
||||
implicit protected def wallet2AppConfig: WalletAppConfig = {
|
||||
config2.walletConf
|
||||
|
@ -224,7 +224,7 @@ class TrezorAddressTest extends BitcoinSWalletTest with EmptyFixture {
|
||||
private def testAccountType(purpose: HDPurpose): Future[Assertion] = {
|
||||
val confOverride = configForPurposeAndSeed(purpose)
|
||||
implicit val conf: WalletAppConfig =
|
||||
BitcoinSTestAppConfig.getSpvTestConfig(confOverride).walletConf
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig(confOverride).walletConf
|
||||
|
||||
val testVectors = purpose match {
|
||||
case HDPurposes.Legacy => legacyVectors
|
||||
|
@ -1,61 +0,0 @@
|
||||
package org.bitcoins.wallet
|
||||
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.testkitcore.Implicits._
|
||||
import org.bitcoins.testkit.wallet.{
|
||||
BitcoinSWalletTestCachedBitcoindNewest,
|
||||
WalletWithBitcoind,
|
||||
WalletWithBitcoindRpc
|
||||
}
|
||||
import org.scalatest.{FutureOutcome, Outcome}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class WalletBloomTest extends BitcoinSWalletTestCachedBitcoindNewest {
|
||||
behavior of "Wallet bloom filter"
|
||||
|
||||
override type FixtureParam = WalletWithBitcoind
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
|
||||
val f: Future[Outcome] = for {
|
||||
bitcoind <- cachedBitcoindWithFundsF
|
||||
futOutcome = withFundedWalletAndBitcoindCached(
|
||||
test,
|
||||
getBIP39PasswordOpt(),
|
||||
bitcoind)(getFreshWalletAppConfig)
|
||||
fut <- futOutcome.toFuture
|
||||
} yield fut
|
||||
new FutureOutcome(f)
|
||||
}
|
||||
|
||||
it should "generate a bloom filter that matches the pubkeys in our wallet" in {
|
||||
param =>
|
||||
val WalletWithBitcoindRpc(walletApi, _) = param
|
||||
val wallet = walletApi.asInstanceOf[Wallet]
|
||||
for {
|
||||
_ <- FutureUtil.sequentially(0 until 10)(_ => wallet.getNewAddress())
|
||||
bloom <- wallet.getBloomFilter()
|
||||
pubkeys <- wallet.listPubkeys()
|
||||
} yield {
|
||||
pubkeys.map { pub =>
|
||||
assert(bloom.contains(pub))
|
||||
}.toAssertion
|
||||
}
|
||||
}
|
||||
|
||||
it should "generate a bloom filter that matches the outpoints in our wallet" in {
|
||||
param =>
|
||||
val WalletWithBitcoindRpc(walletApi, _) = param
|
||||
val wallet = walletApi.asInstanceOf[Wallet]
|
||||
|
||||
for {
|
||||
outpoints <- wallet.listOutpoints()
|
||||
|
||||
bloom <- wallet.getBloomFilter()
|
||||
} yield {
|
||||
outpoints.map { out =>
|
||||
assert(bloom.contains(out))
|
||||
}.toAssertion
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import org.bitcoins.core.api.wallet.{
|
||||
BlockSyncState,
|
||||
CoinSelectionAlgo
|
||||
}
|
||||
import org.bitcoins.core.bloom.{BloomFilter, BloomUpdateAll}
|
||||
import org.bitcoins.core.config.BitcoinNetwork
|
||||
import org.bitcoins.core.crypto.ExtPublicKey
|
||||
import org.bitcoins.core.currency._
|
||||
@ -374,45 +373,6 @@ abstract class Wallet
|
||||
protected[wallet] def listOutpoints(): Future[Vector[TransactionOutPoint]] =
|
||||
spendingInfoDAO.findAllOutpoints()
|
||||
|
||||
/** Gets the size of the bloom filter for this wallet */
|
||||
private def getBloomFilterSize(
|
||||
pubkeys: Seq[ECPublicKey],
|
||||
outpoints: Seq[TransactionOutPoint]): Int = {
|
||||
// when a public key is inserted into a filter
|
||||
// both the pubkey and the hash of the pubkey
|
||||
// gets inserted
|
||||
pubkeys.length * 2
|
||||
} + outpoints.length
|
||||
|
||||
// todo: insert TXIDs? need to track which txids we should
|
||||
// ask for, somehow
|
||||
// We add all outpoints to the bloom filter as a way
|
||||
// of working around the fact that bloom filters
|
||||
// was never updated to incorporate SegWit changes.
|
||||
// see this mailing list thread for context:
|
||||
// https://www.mail-archive.com/bitcoin-dev@lists.linuxfoundation.org/msg06950.html
|
||||
// especially this email from Jim Posen:
|
||||
// https://www.mail-archive.com/bitcoin-dev@lists.linuxfoundation.org/msg06952.html
|
||||
override def getBloomFilter(): Future[BloomFilter] = {
|
||||
for {
|
||||
pubkeys <- listPubkeys()
|
||||
outpoints <- listOutpoints()
|
||||
} yield {
|
||||
val filterSize = getBloomFilterSize(pubkeys, outpoints)
|
||||
|
||||
// todo: Is this the best flag to use?
|
||||
val bloomFlag = BloomUpdateAll
|
||||
|
||||
val baseBloom =
|
||||
BloomFilter(numElements = filterSize,
|
||||
falsePositiveRate = walletConfig.bloomFalsePositiveRate,
|
||||
flags = bloomFlag)
|
||||
|
||||
val withPubs = pubkeys.foldLeft(baseBloom) { _.insert(_) }
|
||||
outpoints.foldLeft(withPubs) { _.insert(_) }
|
||||
}
|
||||
}
|
||||
|
||||
/** Takes a [[RawTxBuilderWithFinalizer]] for a transaction to be sent, and completes it by:
|
||||
* finalizing and signing the transaction, then correctly processing and logging it
|
||||
*/
|
||||
|
@ -100,10 +100,6 @@ private[wallet] trait RescanHandling extends WalletLogger {
|
||||
} yield rescanState
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
override def rescanSPVWallet(): Future[Unit] =
|
||||
Future.failed(new RuntimeException("Rescan not implemented for SPV wallet"))
|
||||
|
||||
lazy val walletCreationBlockHeight: Future[BlockHeight] =
|
||||
chainQueryApi
|
||||
.epochSecondToBlockHeight(creationTime.getEpochSecond)
|
||||
|
Loading…
Reference in New Issue
Block a user