mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-26 13:25:49 +01:00
2024 07 31 bitcoind callbacks (#5631)
* Add NodeApiCallbacks * Add BitcoindCallbacks * Add BitcoindRpcAppConfig * fix docs * Add helper method for construction * Add helper constructor method to avoid explicitly passing BitcoindRpcAppConfig parameter to BitcoindRpcClient when we have a BitcoindInstanceLocal * Fix docs
This commit is contained in:
parent
88b1dfd4c5
commit
38850d22e3
22 changed files with 200 additions and 155 deletions
|
@ -3,13 +3,14 @@ package org.bitcoins.server.util
|
|||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.apache.pekko.stream.scaladsl.{Sink, Source}
|
||||
import org.bitcoins.commons.util.BitcoinSLogger
|
||||
import org.bitcoins.core.api.callback.OnBlockReceived
|
||||
import org.bitcoins.core.api.dlc.wallet.DLCNeutrinoHDWalletApi
|
||||
import org.bitcoins.core.api.wallet.{NeutrinoWalletApi, WalletApi}
|
||||
import org.bitcoins.core.gcs.GolombFilter
|
||||
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader}
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.node.*
|
||||
import org.bitcoins.node.callback.NodeCallbackStreamManager
|
||||
import org.bitcoins.wallet.WalletNotInitialized
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
|||
.isInstanceOf[BitcoindAuthCredentials.CookieBased]
|
||||
)
|
||||
|
||||
val cli = BitcoindRpcClient.withActorSystem(instance)
|
||||
val cli = BitcoindRpcClient(instance)
|
||||
testClientStart(cli)
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
|||
instance.authCredentials
|
||||
.isInstanceOf[BitcoindAuthCredentials.PasswordBased]
|
||||
)
|
||||
testClientStart(BitcoindRpcClient.withActorSystem(instance))
|
||||
testClientStart(BitcoindRpcClient(instance))
|
||||
}
|
||||
|
||||
// the values in this conf was generated by executing
|
||||
|
@ -132,13 +132,14 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
|||
binary = newestBitcoindBinary
|
||||
)
|
||||
|
||||
testClientStart(BitcoindRpcClient.withActorSystem(instance))
|
||||
testClientStart(BitcoindRpcClient(instance))
|
||||
}
|
||||
|
||||
it should "parse a bitcoin.conf file, start bitcoind, mine some blocks and quit" in {
|
||||
val instance =
|
||||
BitcoindInstanceLocal.fromDatadir(datadir.toFile, newestBitcoindBinary)
|
||||
val client = BitcoindRpcClient.withActorSystem(instance)
|
||||
val client =
|
||||
BitcoindRpcClient(instance)
|
||||
|
||||
for {
|
||||
_ <- startClient(client)
|
||||
|
@ -185,7 +186,8 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
|||
binary = newestBitcoindBinary
|
||||
)
|
||||
|
||||
val client = BitcoindRpcClient.withActorSystem(instance)
|
||||
val client =
|
||||
BitcoindRpcClient(instance)
|
||||
for {
|
||||
_ <- startClient(client)
|
||||
remoteInstance = BitcoindInstanceRemote(
|
||||
|
@ -196,7 +198,9 @@ class BitcoindInstanceTest extends BitcoindRpcTest {
|
|||
zmqConfig = instance.zmqConfig,
|
||||
proxyParams = None
|
||||
)
|
||||
remoteClient = BitcoindRpcClient.withActorSystem(remoteInstance)
|
||||
remoteClient = new BitcoindRpcClient(remoteInstance)(
|
||||
system,
|
||||
instance.bitcoindRpcAppConfig)
|
||||
_ <- remoteClient.start()
|
||||
_ <- remoteClient.isStartedF.map {
|
||||
case false =>
|
||||
|
|
|
@ -66,10 +66,10 @@ class WalletRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
|
||||
// This client's wallet is encrypted
|
||||
lazy val walletClientF: Future[BitcoindRpcClient] = clientsF.flatMap { _ =>
|
||||
val instance =
|
||||
BitcoindRpcTestUtil.instance(versionOpt = Some(BitcoindVersion.newest))
|
||||
val walletClient =
|
||||
BitcoindRpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.instance(versionOpt = Some(BitcoindVersion.newest))
|
||||
)
|
||||
BitcoindRpcClient(instance)
|
||||
|
||||
for {
|
||||
_ <- startClient(walletClient)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package org.bitcoins.rpc
|
||||
|
||||
import org.bitcoins.commons.util.BitcoinSLogger
|
||||
import org.bitcoins.core.api.CallbackHandler
|
||||
import org.bitcoins.core.api.callback.{
|
||||
CallbackFactory,
|
||||
ModuleCallbacks,
|
||||
NodeApiCallbacks,
|
||||
OnBlockReceived
|
||||
}
|
||||
import org.bitcoins.core.protocol.blockchain.Block
|
||||
|
||||
trait BitcoindCallbacks
|
||||
extends NodeApiCallbacks
|
||||
with ModuleCallbacks[BitcoindCallbacks]
|
||||
with BitcoinSLogger
|
||||
|
||||
object BitcoindCallbacks extends CallbackFactory[BitcoindCallbacks] {
|
||||
private case class BitcoindCallbacksImpl(
|
||||
onBlockReceived: CallbackHandler[Block, OnBlockReceived])
|
||||
extends BitcoindCallbacks {
|
||||
override def +(other: BitcoindCallbacks): BitcoindCallbacks = {
|
||||
copy(onBlockReceived = onBlockReceived ++ other.onBlockReceived)
|
||||
}
|
||||
}
|
||||
override def empty: BitcoindCallbacks = BitcoindCallbacksImpl(
|
||||
CallbackHandler.empty)
|
||||
|
||||
/** Constructs a set of callbacks that only acts on block received */
|
||||
def onBlockReceived(f: OnBlockReceived): BitcoindCallbacks = {
|
||||
BitcoindCallbacksImpl(onBlockReceived =
|
||||
CallbackHandler[Block, OnBlockReceived](
|
||||
"onBlockReceived",
|
||||
Vector(f)
|
||||
))
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package org.bitcoins.rpc.client.common
|
||||
|
||||
import org.apache.pekko.Done
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.apache.pekko.stream.scaladsl.{Keep, RunnableGraph, Sink, Source}
|
||||
import org.bitcoins.commons.util.BitcoinSLogger
|
||||
import org.bitcoins.core.api.chain.db.BlockHeaderDb
|
||||
import org.bitcoins.core.api.chain.{ChainApi, FilterSyncMarker}
|
||||
|
@ -19,7 +21,7 @@ import org.bitcoins.rpc.client.v20.V20MultisigRpc
|
|||
import org.bitcoins.rpc.client.v25.BitcoindV25RpcClient
|
||||
import org.bitcoins.rpc.client.v26.BitcoindV26RpcClient
|
||||
import org.bitcoins.rpc.client.v27.BitcoindV27RpcClient
|
||||
import org.bitcoins.rpc.config._
|
||||
import org.bitcoins.rpc.config.*
|
||||
|
||||
import java.io.File
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
@ -35,7 +37,8 @@ import scala.concurrent.Future
|
|||
* handle them as you see fit.
|
||||
*/
|
||||
class BitcoindRpcClient(override val instance: BitcoindInstance)(implicit
|
||||
override val system: ActorSystem
|
||||
override val system: ActorSystem,
|
||||
bitcoindRpcAppConfig: BitcoindRpcAppConfig
|
||||
) extends Client
|
||||
with FeeRateApi
|
||||
with NodeApi
|
||||
|
@ -166,7 +169,17 @@ class BitcoindRpcClient(override val instance: BitcoindInstance)(implicit
|
|||
|
||||
override def downloadBlocks(
|
||||
blockHashes: Vector[DoubleSha256DigestBE]
|
||||
): Future[Unit] = Future.unit
|
||||
): Future[Unit] = {
|
||||
val callback =
|
||||
bitcoindRpcAppConfig.callBacks.executeOnBlockReceivedCallbacks(_)
|
||||
val graph: RunnableGraph[Future[Done]] = Source(blockHashes)
|
||||
.mapAsync(FutureUtil.getParallelism)(getBlockRaw)
|
||||
.toMat(Sink.foreachAsync(1)(callback))(Keep.right)
|
||||
|
||||
graph
|
||||
.run()
|
||||
.map(_ => ())
|
||||
}
|
||||
|
||||
override def processHeaders(headers: Vector[BlockHeader]): Future[ChainApi] =
|
||||
Future.successful(this)
|
||||
|
@ -294,35 +307,16 @@ class BitcoindRpcClient(override val instance: BitcoindInstance)(implicit
|
|||
}
|
||||
|
||||
object BitcoindRpcClient {
|
||||
|
||||
/** The name we give to actor systems we create. We use this information to
|
||||
* know which actor systems to shut down
|
||||
*/
|
||||
private[rpc] val ActorSystemName = "bitcoind-rpc-client-created-by-bitcoin-s"
|
||||
|
||||
implicit private lazy val system: ActorSystem =
|
||||
ActorSystem.create(ActorSystemName)
|
||||
|
||||
val DEFAULT_WALLET_NAME: String = "wallet.dat"
|
||||
|
||||
/** Creates an RPC client from the given instance.
|
||||
*
|
||||
* Behind the scenes, we create an actor system for you. You can use
|
||||
* `withActorSystem` if you want to manually specify an actor system for the
|
||||
* RPC client.
|
||||
*/
|
||||
def apply(instance: BitcoindInstance): BitcoindRpcClient = {
|
||||
withActorSystem(instance)(system)
|
||||
}
|
||||
|
||||
/** Creates an RPC client from the given instance, together with the given
|
||||
* actor system. This is for advanced users, where you need fine grained
|
||||
* control over the RPC client.
|
||||
*/
|
||||
def withActorSystem(instance: BitcoindInstance)(implicit
|
||||
def apply(instance: BitcoindInstanceLocal)(implicit
|
||||
system: ActorSystem
|
||||
): BitcoindRpcClient =
|
||||
new BitcoindRpcClient(instance)
|
||||
new BitcoindRpcClient(instance)(system, instance.bitcoindRpcAppConfig)
|
||||
|
||||
/** Constructs a RPC client from the given datadir, or the default datadir if
|
||||
* no directory is provided. This is always a [[BitcoindInstanceLocal]] since
|
||||
|
@ -331,7 +325,7 @@ object BitcoindRpcClient {
|
|||
def fromDatadir(
|
||||
datadir: File = BitcoindConfig.DEFAULT_DATADIR,
|
||||
binary: File
|
||||
): BitcoindRpcClient = {
|
||||
)(implicit system: ActorSystem): BitcoindRpcClient = {
|
||||
val instance = BitcoindInstanceLocal.fromDatadir(datadir, binary)
|
||||
val cli = BitcoindRpcClient(instance)
|
||||
cli
|
||||
|
@ -340,13 +334,13 @@ object BitcoindRpcClient {
|
|||
/** Returns a bitcoind with the appropriated version you passed in, the
|
||||
* bitcoind is NOT started.
|
||||
*/
|
||||
def fromVersion(version: BitcoindVersion, instance: BitcoindInstance)(implicit
|
||||
system: ActorSystem
|
||||
def fromVersion(version: BitcoindVersion, instance: BitcoindInstanceLocal)(
|
||||
implicit system: ActorSystem
|
||||
): BitcoindRpcClient = {
|
||||
val bitcoind = version match {
|
||||
case BitcoindVersion.V25 => BitcoindV25RpcClient.withActorSystem(instance)
|
||||
case BitcoindVersion.V26 => BitcoindV26RpcClient.withActorSystem(instance)
|
||||
case BitcoindVersion.V27 => BitcoindV27RpcClient.withActorSystem(instance)
|
||||
case BitcoindVersion.V25 => BitcoindV25RpcClient(instance)
|
||||
case BitcoindVersion.V26 => BitcoindV26RpcClient(instance)
|
||||
case BitcoindVersion.V27 => BitcoindV27RpcClient(instance)
|
||||
case BitcoindVersion.Unknown =>
|
||||
sys.error(
|
||||
s"Cannot create a Bitcoin Core RPC client: unsupported version"
|
||||
|
@ -355,11 +349,24 @@ object BitcoindRpcClient {
|
|||
bitcoind
|
||||
}
|
||||
|
||||
def fromVersionNoSystem(
|
||||
version: BitcoindVersion,
|
||||
instance: BitcoindInstance
|
||||
/** Returns a bitcoind with the appropriated version you passed in, the
|
||||
* bitcoind is NOT started.
|
||||
*/
|
||||
def fromVersion(version: BitcoindVersion, instance: BitcoindInstanceRemote)(
|
||||
implicit
|
||||
system: ActorSystem,
|
||||
bitcoindRpcAppConfig: BitcoindRpcAppConfig
|
||||
): BitcoindRpcClient = {
|
||||
fromVersion(version, instance)(system)
|
||||
val bitcoind = version match {
|
||||
case BitcoindVersion.V25 => new BitcoindV25RpcClient(instance)
|
||||
case BitcoindVersion.V26 => new BitcoindV26RpcClient(instance)
|
||||
case BitcoindVersion.V27 => new BitcoindV27RpcClient(instance)
|
||||
case BitcoindVersion.Unknown =>
|
||||
sys.error(
|
||||
s"Cannot create a Bitcoin Core RPC client: unsupported version"
|
||||
)
|
||||
}
|
||||
bitcoind
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -323,11 +323,6 @@ trait Client
|
|||
// i think bitcoind stops asynchronously
|
||||
// so it returns fast from the 'stop' rpc command
|
||||
_ <- stopBinary()
|
||||
_ <- {
|
||||
if (system.name == BitcoindRpcClient.ActorSystemName) {
|
||||
system.terminate()
|
||||
} else Future.unit
|
||||
}
|
||||
} yield this.asInstanceOf[BitcoindRpcClient]
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,17 @@ package org.bitcoins.rpc.client.v25
|
|||
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.config.BitcoindInstance
|
||||
import org.bitcoins.rpc.config.{
|
||||
BitcoindInstance,
|
||||
BitcoindInstanceLocal,
|
||||
BitcoindRpcAppConfig
|
||||
}
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Try
|
||||
|
||||
class BitcoindV25RpcClient(override val instance: BitcoindInstance)(implicit
|
||||
actorSystem: ActorSystem
|
||||
actorSystem: ActorSystem,
|
||||
bitcoindRpcAppConfig: BitcoindRpcAppConfig
|
||||
) extends BitcoindRpcClient(instance) {
|
||||
|
||||
override lazy val version: Future[BitcoindVersion] =
|
||||
|
@ -17,32 +21,13 @@ class BitcoindV25RpcClient(override val instance: BitcoindInstance)(implicit
|
|||
|
||||
object BitcoindV25RpcClient {
|
||||
|
||||
/** Creates an RPC client from the given instance.
|
||||
*
|
||||
* Behind the scenes, we create an actor system for you. You can use
|
||||
* `withActorSystem` if you want to manually specify an actor system for the
|
||||
* RPC client.
|
||||
*/
|
||||
def apply(instance: BitcoindInstance): BitcoindV25RpcClient = {
|
||||
implicit val system: ActorSystem =
|
||||
ActorSystem.create(BitcoindRpcClient.ActorSystemName)
|
||||
withActorSystem(instance)
|
||||
}
|
||||
|
||||
/** Creates an RPC client from the given instance, together with the given
|
||||
* actor system. This is for advanced users, where you need fine grained
|
||||
* control over the RPC client.
|
||||
*/
|
||||
def withActorSystem(instance: BitcoindInstance)(implicit
|
||||
def apply(instance: BitcoindInstanceLocal)(implicit
|
||||
system: ActorSystem
|
||||
): BitcoindV25RpcClient =
|
||||
new BitcoindV25RpcClient(instance)(system)
|
||||
|
||||
def fromUnknownVersion(
|
||||
rpcClient: BitcoindRpcClient
|
||||
): Try[BitcoindV25RpcClient] =
|
||||
Try {
|
||||
new BitcoindV25RpcClient(rpcClient.instance)(rpcClient.system)
|
||||
}
|
||||
new BitcoindV25RpcClient(instance)(system, instance.bitcoindRpcAppConfig)
|
||||
|
||||
}
|
||||
|
|
|
@ -2,13 +2,17 @@ package org.bitcoins.rpc.client.v26
|
|||
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.config.BitcoindInstance
|
||||
import org.bitcoins.rpc.config.{
|
||||
BitcoindInstance,
|
||||
BitcoindInstanceLocal,
|
||||
BitcoindRpcAppConfig
|
||||
}
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Try
|
||||
|
||||
class BitcoindV26RpcClient(override val instance: BitcoindInstance)(implicit
|
||||
actorSystem: ActorSystem
|
||||
actorSystem: ActorSystem,
|
||||
bitcoindRpcAppConfig: BitcoindRpcAppConfig
|
||||
) extends BitcoindRpcClient(instance) {
|
||||
|
||||
override lazy val version: Future[BitcoindVersion] =
|
||||
|
@ -17,32 +21,13 @@ class BitcoindV26RpcClient(override val instance: BitcoindInstance)(implicit
|
|||
|
||||
object BitcoindV26RpcClient {
|
||||
|
||||
/** Creates an RPC client from the given instance.
|
||||
*
|
||||
* Behind the scenes, we create an actor system for you. You can use
|
||||
* `withActorSystem` if you want to manually specify an actor system for the
|
||||
* RPC client.
|
||||
*/
|
||||
def apply(instance: BitcoindInstance): BitcoindV26RpcClient = {
|
||||
implicit val system: ActorSystem =
|
||||
ActorSystem.create(BitcoindRpcClient.ActorSystemName)
|
||||
withActorSystem(instance)
|
||||
}
|
||||
|
||||
/** Creates an RPC client from the given instance, together with the given
|
||||
* actor system. This is for advanced users, where you need fine grained
|
||||
* control over the RPC client.
|
||||
*/
|
||||
def withActorSystem(instance: BitcoindInstance)(implicit
|
||||
def apply(instance: BitcoindInstanceLocal)(implicit
|
||||
system: ActorSystem
|
||||
): BitcoindV26RpcClient =
|
||||
new BitcoindV26RpcClient(instance)(system)
|
||||
|
||||
def fromUnknownVersion(
|
||||
rpcClient: BitcoindRpcClient
|
||||
): Try[BitcoindV26RpcClient] =
|
||||
Try {
|
||||
new BitcoindV26RpcClient(rpcClient.instance)(rpcClient.system)
|
||||
}
|
||||
new BitcoindV26RpcClient(instance)(system, instance.bitcoindRpcAppConfig)
|
||||
|
||||
}
|
||||
|
|
|
@ -2,13 +2,17 @@ package org.bitcoins.rpc.client.v27
|
|||
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.config.BitcoindInstance
|
||||
import org.bitcoins.rpc.config.{
|
||||
BitcoindInstance,
|
||||
BitcoindInstanceLocal,
|
||||
BitcoindRpcAppConfig
|
||||
}
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Try
|
||||
|
||||
class BitcoindV27RpcClient(override val instance: BitcoindInstance)(implicit
|
||||
actorSystem: ActorSystem
|
||||
actorSystem: ActorSystem,
|
||||
bitcoindRpcAppConfig: BitcoindRpcAppConfig
|
||||
) extends BitcoindRpcClient(instance) {
|
||||
|
||||
override lazy val version: Future[BitcoindVersion] =
|
||||
|
@ -17,32 +21,13 @@ class BitcoindV27RpcClient(override val instance: BitcoindInstance)(implicit
|
|||
|
||||
object BitcoindV27RpcClient {
|
||||
|
||||
/** Creates an RPC client from the given instance.
|
||||
*
|
||||
* Behind the scenes, we create an actor system for you. You can use
|
||||
* `withActorSystem` if you want to manually specify an actor system for the
|
||||
* RPC client.
|
||||
*/
|
||||
def apply(instance: BitcoindInstance): BitcoindV27RpcClient = {
|
||||
implicit val system: ActorSystem =
|
||||
ActorSystem.create(BitcoindRpcClient.ActorSystemName)
|
||||
withActorSystem(instance)
|
||||
}
|
||||
|
||||
/** Creates an RPC client from the given instance, together with the given
|
||||
* actor system. This is for advanced users, where you need fine grained
|
||||
* control over the RPC client.
|
||||
*/
|
||||
def withActorSystem(instance: BitcoindInstance)(implicit
|
||||
def apply(instance: BitcoindInstanceLocal)(implicit
|
||||
system: ActorSystem
|
||||
): BitcoindV27RpcClient =
|
||||
new BitcoindV27RpcClient(instance)(system)
|
||||
|
||||
def fromUnknownVersion(
|
||||
rpcClient: BitcoindRpcClient
|
||||
): Try[BitcoindV27RpcClient] =
|
||||
Try {
|
||||
new BitcoindV27RpcClient(rpcClient.instance)(rpcClient.system)
|
||||
}
|
||||
new BitcoindV27RpcClient(instance)(system, instance.bitcoindRpcAppConfig)
|
||||
|
||||
}
|
||||
|
|
|
@ -77,6 +77,10 @@ sealed trait BitcoindInstanceLocal extends BitcoindInstance {
|
|||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
def bitcoindRpcAppConfig: BitcoindRpcAppConfig = {
|
||||
BitcoindRpcAppConfig.fromDatadir(datadir.toPath)
|
||||
}
|
||||
}
|
||||
|
||||
/** Refers to a bitcoind instance that is running remotely on another machine */
|
||||
|
|
|
@ -4,7 +4,10 @@ import com.typesafe.config.Config
|
|||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.asyncutil.AsyncUtil
|
||||
import org.bitcoins.commons.config.{AppConfig, ConfigOps}
|
||||
import org.bitcoins.core.api.CallbackConfig
|
||||
import org.bitcoins.core.api.callback.CallbackFactory
|
||||
import org.bitcoins.core.api.tor.Socks5ProxyParams
|
||||
import org.bitcoins.rpc.BitcoindCallbacks
|
||||
import org.bitcoins.rpc.BitcoindException.InWarmUp
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.util.AppConfigFactoryActorSystem
|
||||
|
@ -12,7 +15,7 @@ import org.bitcoins.tor.config.TorAppConfig
|
|||
|
||||
import java.io.File
|
||||
import java.net.{InetSocketAddress, URI}
|
||||
import java.nio.file._
|
||||
import java.nio.file.*
|
||||
import scala.concurrent.duration.DurationInt
|
||||
import scala.concurrent.{Future, Promise}
|
||||
|
||||
|
@ -26,7 +29,8 @@ case class BitcoindRpcAppConfig(
|
|||
baseDatadir: Path,
|
||||
configOverrides: Vector[Config]
|
||||
)(implicit val system: ActorSystem)
|
||||
extends AppConfig {
|
||||
extends AppConfig
|
||||
with CallbackConfig[BitcoindCallbacks] {
|
||||
|
||||
import system.dispatcher
|
||||
|
||||
|
@ -180,12 +184,13 @@ case class BitcoindRpcAppConfig(
|
|||
bitcoindInstance match {
|
||||
case local: BitcoindInstanceLocal =>
|
||||
val version = versionOpt.getOrElse(local.getVersion)
|
||||
val client = BitcoindRpcClient.fromVersion(version, bitcoindInstance)
|
||||
val client =
|
||||
BitcoindRpcClient.fromVersion(version, local)
|
||||
Future.successful(client)
|
||||
case _: BitcoindInstanceRemote =>
|
||||
case remote: BitcoindInstanceRemote =>
|
||||
// first get a generic rpc client so we can retrieve
|
||||
// the proper version of the remote running bitcoind
|
||||
val noVersionRpc = new BitcoindRpcClient(bitcoindInstance)
|
||||
val noVersionRpc = new BitcoindRpcClient(remote)(system, this)
|
||||
val versionF = getBitcoindVersion(noVersionRpc)
|
||||
|
||||
// if we don't retrieve the proper version, we can
|
||||
|
@ -194,7 +199,8 @@ case class BitcoindRpcAppConfig(
|
|||
// such as blockfilters
|
||||
// see: https://github.com/bitcoin-s/bitcoin-s/issues/3695#issuecomment-929492945
|
||||
versionF.map { version =>
|
||||
BitcoindRpcClient.fromVersion(version, instance = bitcoindInstance)
|
||||
BitcoindRpcClient.fromVersion(version, instance = remote)(system,
|
||||
this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,6 +233,9 @@ case class BitcoindRpcAppConfig(
|
|||
version
|
||||
}
|
||||
}
|
||||
|
||||
override def callbackFactory: CallbackFactory[BitcoindCallbacks] =
|
||||
BitcoindCallbacks
|
||||
}
|
||||
|
||||
object BitcoindRpcAppConfig
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.bitcoins.core.api.callback
|
||||
|
||||
import org.bitcoins.core.api.{Callback, CallbackHandler}
|
||||
import org.bitcoins.core.protocol.blockchain.Block
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
/** Callback for handling a received block */
|
||||
trait OnBlockReceived extends Callback[Block]
|
||||
|
||||
trait NodeApiCallbacks {
|
||||
def onBlockReceived: CallbackHandler[Block, OnBlockReceived]
|
||||
def executeOnBlockReceivedCallbacks(
|
||||
block: Block
|
||||
)(implicit ec: ExecutionContext): Future[Unit] = {
|
||||
onBlockReceived.execute(block)
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ title: Chain Query API
|
|||
|
||||
```scala mdoc:invisible
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.core.api.callback.OnBlockReceived
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi.FilterResponse
|
||||
import org.bitcoins.crypto._
|
||||
|
|
|
@ -4,6 +4,7 @@ id: node-api title: Node API
|
|||
|
||||
```scala mdoc:invisible
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.core.api.callback.OnBlockReceived
|
||||
import org.bitcoins.core.api.node._
|
||||
import org.bitcoins.crypto._
|
||||
import org.bitcoins.core.protocol.blockchain.Block
|
||||
|
|
|
@ -43,6 +43,7 @@ For your node to be able to service these filters you will need set
|
|||
```scala mdoc:invisible
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.chain.config.ChainAppConfig
|
||||
import org.bitcoins.core.api.callback.OnBlockReceived
|
||||
import org.bitcoins.core.protocol.blockchain.Block
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
|
|
|
@ -130,8 +130,8 @@ class is only intended to cover errors returned by Bitcoin Core. An example of h
|
|||
handling could look:
|
||||
|
||||
```scala mdoc:compile-only
|
||||
|
||||
implicit val ec: ExecutionContext = ExecutionContext.global
|
||||
implicit val system: ActorSystem = ActorSystem()
|
||||
implicit val ec: ExecutionContext = system.dispatcher
|
||||
|
||||
// let's assume you have an already running client,
|
||||
// so there's no need to start this one
|
||||
|
|
|
@ -3,15 +3,16 @@ package org.bitcoins.node.networking.peer
|
|||
import com.typesafe.config.ConfigFactory
|
||||
import org.bitcoins.asyncutil.AsyncUtil
|
||||
import org.bitcoins.chain.blockchain.ChainHandler
|
||||
import org.bitcoins.core.api.callback.OnBlockReceived
|
||||
import org.bitcoins.core.config.SigNet
|
||||
import org.bitcoins.core.currency._
|
||||
import org.bitcoins.core.currency.*
|
||||
import org.bitcoins.core.gcs.{FilterType, GolombFilter}
|
||||
import org.bitcoins.core.p2p.HeadersMessage
|
||||
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader}
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.node.NodeState.{FilterHeaderSync, HeaderSync}
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.node.*
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.node.fixture.NeutrinoNodeConnectedWithBitcoind
|
||||
|
|
|
@ -2,7 +2,12 @@ package org.bitcoins.node
|
|||
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.commons.util.BitcoinSLogger
|
||||
import org.bitcoins.core.api.callback.{CallbackFactory, ModuleCallbacks}
|
||||
import org.bitcoins.core.api.callback.{
|
||||
CallbackFactory,
|
||||
ModuleCallbacks,
|
||||
NodeApiCallbacks,
|
||||
OnBlockReceived
|
||||
}
|
||||
import org.bitcoins.core.api.{Callback, Callback2, CallbackHandler}
|
||||
import org.bitcoins.core.gcs.GolombFilter
|
||||
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader, MerkleBlock}
|
||||
|
@ -15,7 +20,10 @@ import scala.concurrent.{ExecutionContext, Future}
|
|||
/** Callbacks for responding to events in the node. The appropriate callback is
|
||||
* executed whenever the node receives a `getdata` message matching it.
|
||||
*/
|
||||
trait NodeCallbacks extends ModuleCallbacks[NodeCallbacks] with BitcoinSLogger {
|
||||
trait NodeCallbacks
|
||||
extends ModuleCallbacks[NodeCallbacks]
|
||||
with NodeApiCallbacks
|
||||
with BitcoinSLogger {
|
||||
|
||||
def onCompactFiltersReceived
|
||||
: CallbackHandler[Vector[
|
||||
|
@ -25,8 +33,6 @@ trait NodeCallbacks extends ModuleCallbacks[NodeCallbacks] with BitcoinSLogger {
|
|||
|
||||
def onTxReceived: CallbackHandler[Transaction, OnTxReceived]
|
||||
|
||||
def onBlockReceived: CallbackHandler[Block, OnBlockReceived]
|
||||
|
||||
def onMerkleBlockReceived: CallbackHandler[
|
||||
(MerkleBlock, Vector[Transaction]),
|
||||
OnMerkleBlockReceived
|
||||
|
@ -47,7 +53,7 @@ trait NodeCallbacks extends ModuleCallbacks[NodeCallbacks] with BitcoinSLogger {
|
|||
)
|
||||
}
|
||||
|
||||
def executeOnBlockReceivedCallbacks(
|
||||
override def executeOnBlockReceivedCallbacks(
|
||||
block: Block
|
||||
)(implicit ec: ExecutionContext): Future[Unit] = {
|
||||
onBlockReceived.execute(
|
||||
|
@ -101,9 +107,6 @@ trait NodeCallbacks extends ModuleCallbacks[NodeCallbacks] with BitcoinSLogger {
|
|||
}
|
||||
}
|
||||
|
||||
/** Callback for handling a received block */
|
||||
trait OnBlockReceived extends Callback[Block]
|
||||
|
||||
/** Callback for handling a received Merkle block with its corresponding TXs */
|
||||
trait OnMerkleBlockReceived extends Callback2[MerkleBlock, Vector[Transaction]]
|
||||
|
||||
|
|
|
@ -11,12 +11,13 @@ import org.apache.pekko.stream.scaladsl.{
|
|||
}
|
||||
import org.bitcoins.commons.util.BitcoinSLogger
|
||||
import org.bitcoins.core.api.CallbackHandler
|
||||
import org.bitcoins.core.api.callback.OnBlockReceived
|
||||
import org.bitcoins.core.gcs.GolombFilter
|
||||
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader, MerkleBlock}
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.core.util.StartStopAsync
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.node.*
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.bitcoins.core.protocol.ln.channel.{
|
|||
import org.bitcoins.core.protocol.ln.currency.MilliSatoshis
|
||||
import org.bitcoins.core.protocol.ln.node.NodeId
|
||||
import org.bitcoins.crypto.Sha256Digest
|
||||
import org.bitcoins.eclair.rpc.api._
|
||||
import org.bitcoins.eclair.rpc.api.*
|
||||
import org.bitcoins.eclair.rpc.client.EclairRpcClient
|
||||
import org.bitcoins.eclair.rpc.config.EclairInstanceLocal
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
|
@ -768,7 +768,7 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
|||
authCredentials = auth.bitcoinAuthOpt.get,
|
||||
binary = BitcoindRpcTestUtil.getBinary(bitcoindVersion)
|
||||
)
|
||||
BitcoindRpcClient.withActorSystem(bitcoindInstance)
|
||||
BitcoindRpcClient(bitcoindInstance)
|
||||
}
|
||||
bitcoindRpc
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@ package org.bitcoins.testkit.fixtures
|
|||
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.config.BitcoindRpcAppConfig
|
||||
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.testkit.util.BitcoinSAsyncFixtureTest
|
||||
import org.scalatest._
|
||||
import org.scalatest.*
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future, Promise}
|
||||
import scala.util.{Failure, Success}
|
||||
|
@ -125,9 +126,11 @@ object BitcoinSFixture {
|
|||
versionOpt = versionOpt,
|
||||
enableNeutrino = enableNeutrino
|
||||
)
|
||||
val appConfig = BitcoindRpcAppConfig.fromDatadir(instance.datadir.toPath)
|
||||
val bitcoind = versionOpt match {
|
||||
case Some(v) => BitcoindRpcClient.fromVersion(v, instance)
|
||||
case None => new BitcoindRpcClient(instance)
|
||||
case Some(v) =>
|
||||
BitcoindRpcClient.fromVersion(v, instance)
|
||||
case None => new BitcoindRpcClient(instance)(system, appConfig)
|
||||
}
|
||||
BitcoindRpcTestUtil.startServers(Vector(bitcoind)).map(_ => bitcoind)
|
||||
}
|
||||
|
|
|
@ -618,10 +618,12 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
system: ActorSystem
|
||||
): Future[(BitcoindRpcClient, BitcoindRpcClient)] = {
|
||||
implicit val ec: ExecutionContextExecutor = system.getDispatcher
|
||||
val instance1 = instance()
|
||||
val instance2 = instance()
|
||||
val client1: BitcoindRpcClient =
|
||||
BitcoindRpcClient.withActorSystem(instance())
|
||||
BitcoindRpcClient(instance1)
|
||||
val client2: BitcoindRpcClient =
|
||||
BitcoindRpcClient.withActorSystem(instance())
|
||||
BitcoindRpcClient(instance2)
|
||||
|
||||
startServers(Vector(client1, client2)).map { _ =>
|
||||
clientAccum ++= List(client1, client2)
|
||||
|
@ -673,16 +675,17 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
val clients: Vector[T] = (0 until numNodes).map { _ =>
|
||||
val rpc = version match {
|
||||
case BitcoindVersion.Unknown =>
|
||||
BitcoindRpcClient.withActorSystem(BitcoindRpcTestUtil.instance())
|
||||
val instance = BitcoindRpcTestUtil.instance()
|
||||
BitcoindRpcClient(instance)
|
||||
case BitcoindVersion.V25 =>
|
||||
BitcoindV25RpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.v25Instance())
|
||||
val instance = BitcoindRpcTestUtil.v25Instance()
|
||||
BitcoindV25RpcClient(instance)
|
||||
case BitcoindVersion.V26 =>
|
||||
BitcoindV26RpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.v26Instance())
|
||||
val instance = BitcoindRpcTestUtil.v26Instance()
|
||||
BitcoindV26RpcClient(instance)
|
||||
case BitcoindVersion.V27 =>
|
||||
BitcoindV27RpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.v27Instance())
|
||||
val instance = BitcoindRpcTestUtil.v27Instance()
|
||||
BitcoindV27RpcClient(instance)
|
||||
}
|
||||
|
||||
// this is safe as long as this method is never
|
||||
|
@ -1071,7 +1074,7 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
)
|
||||
|
||||
// start the bitcoind instance so eclair can properly use it
|
||||
val rpc = BitcoindRpcClient.withActorSystem(instance)
|
||||
val rpc = BitcoindRpcClient(instance)
|
||||
val startedF = startServers(Vector(rpc))
|
||||
|
||||
val blocksToGenerate = 102
|
||||
|
|
Loading…
Add table
Reference in a new issue