mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
2022 04 26 Startup time of appServer
(#4294)
* Make Server's route be async * WIP * Add StartedBitcoinSAppConfig to indicate when tor starts up * Add torStarted flag to getinfo response
This commit is contained in:
parent
67f8ac8294
commit
f4d864fab8
@ -1,6 +1,7 @@
|
|||||||
package org.bitcoins.commons.jsonmodels
|
package org.bitcoins.commons.jsonmodels
|
||||||
|
|
||||||
import org.bitcoins.core.config.{BitcoinNetwork, BitcoinNetworks}
|
import org.bitcoins.core.config.{BitcoinNetwork, BitcoinNetworks}
|
||||||
|
import org.bitcoins.core.serializers.PicklerKeys
|
||||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||||
import ujson._
|
import ujson._
|
||||||
|
|
||||||
@ -8,13 +9,15 @@ import ujson._
|
|||||||
case class BitcoinSServerInfo(
|
case class BitcoinSServerInfo(
|
||||||
network: BitcoinNetwork,
|
network: BitcoinNetwork,
|
||||||
blockHeight: Int,
|
blockHeight: Int,
|
||||||
blockHash: DoubleSha256DigestBE) {
|
blockHash: DoubleSha256DigestBE,
|
||||||
|
torStarted: Boolean) {
|
||||||
|
|
||||||
lazy val toJson: Value = {
|
lazy val toJson: Value = {
|
||||||
Obj(
|
Obj(
|
||||||
"network" -> Str(network.name),
|
PicklerKeys.networkKey -> Str(network.name),
|
||||||
"blockHeight" -> Num(blockHeight),
|
PicklerKeys.blockHeightKey -> Num(blockHeight),
|
||||||
"blockHash" -> Str(blockHash.hex)
|
PicklerKeys.blockHashKey -> Str(blockHash.hex),
|
||||||
|
PicklerKeys.torStartedKey -> Bool(torStarted)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,10 +27,14 @@ object BitcoinSServerInfo {
|
|||||||
def fromJson(json: Value): BitcoinSServerInfo = {
|
def fromJson(json: Value): BitcoinSServerInfo = {
|
||||||
val obj = json.obj
|
val obj = json.obj
|
||||||
|
|
||||||
val network = BitcoinNetworks.fromString(obj("network").str)
|
val network = BitcoinNetworks.fromString(obj(PicklerKeys.networkKey).str)
|
||||||
val height = obj("blockHeight").num.toInt
|
val height = obj(PicklerKeys.blockHeightKey).num.toInt
|
||||||
val blockHash = DoubleSha256DigestBE(obj("blockHash").str)
|
val blockHash = DoubleSha256DigestBE(obj(PicklerKeys.blockHashKey).str)
|
||||||
|
val torStarted = obj(PicklerKeys.torStartedKey).bool
|
||||||
|
|
||||||
BitcoinSServerInfo(network, height, blockHash)
|
BitcoinSServerInfo(network = network,
|
||||||
|
blockHeight = height,
|
||||||
|
blockHash = blockHash,
|
||||||
|
torStarted = torStarted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,11 @@ class OracleServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
for {
|
for {
|
||||||
_ <- conf.start()
|
_ <- conf.start()
|
||||||
oracle = new DLCOracle()
|
oracle = new DLCOracle()
|
||||||
routes = Seq(OracleRoutes(oracle), commonRoutes)
|
routes = Seq(OracleRoutes(oracle), commonRoutes).map(Future.successful)
|
||||||
server = serverArgParser.rpcPortOpt match {
|
server = serverArgParser.rpcPortOpt match {
|
||||||
case Some(rpcport) =>
|
case Some(rpcport) =>
|
||||||
Server(conf = conf,
|
Server(conf = conf,
|
||||||
handlers = routes,
|
handlersF = routes,
|
||||||
rpcbindOpt = bindConfOpt,
|
rpcbindOpt = bindConfOpt,
|
||||||
rpcport = rpcport,
|
rpcport = rpcport,
|
||||||
rpcPassword = conf.rpcPassword,
|
rpcPassword = conf.rpcPassword,
|
||||||
@ -39,7 +39,7 @@ class OracleServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
Source.empty)
|
Source.empty)
|
||||||
case None =>
|
case None =>
|
||||||
Server(conf = conf,
|
Server(conf = conf,
|
||||||
handlers = routes,
|
handlersF = routes,
|
||||||
rpcbindOpt = bindConfOpt,
|
rpcbindOpt = bindConfOpt,
|
||||||
rpcport = conf.rpcPort,
|
rpcport = conf.rpcPort,
|
||||||
rpcPassword = conf.rpcPassword,
|
rpcPassword = conf.rpcPassword,
|
||||||
|
@ -8,7 +8,14 @@ import akka.http.scaladsl.model.ws.Message
|
|||||||
import akka.http.scaladsl.server.Directives._
|
import akka.http.scaladsl.server.Directives._
|
||||||
import akka.http.scaladsl.server._
|
import akka.http.scaladsl.server._
|
||||||
import akka.http.scaladsl.server.directives.Credentials.Missing
|
import akka.http.scaladsl.server.directives.Credentials.Missing
|
||||||
import akka.http.scaladsl.server.directives.{Credentials, DebuggingDirectives}
|
import akka.http.scaladsl.server.directives.{
|
||||||
|
Credentials,
|
||||||
|
DebuggingDirectives,
|
||||||
|
MarshallingDirectives,
|
||||||
|
MethodDirectives,
|
||||||
|
PathDirectives
|
||||||
|
}
|
||||||
|
import akka.http.scaladsl.unmarshalling.FromRequestUnmarshaller
|
||||||
import akka.stream.scaladsl.{Flow, Sink, Source}
|
import akka.stream.scaladsl.{Flow, Sink, Source}
|
||||||
import akka.{Done, NotUsed}
|
import akka.{Done, NotUsed}
|
||||||
import de.heikoseeberger.akkahttpupickle.UpickleSupport._
|
import de.heikoseeberger.akkahttpupickle.UpickleSupport._
|
||||||
@ -20,7 +27,7 @@ import scala.concurrent.Future
|
|||||||
|
|
||||||
case class Server(
|
case class Server(
|
||||||
conf: AppConfig,
|
conf: AppConfig,
|
||||||
handlers: Seq[ServerRoute],
|
handlersF: Seq[Future[ServerRoute]],
|
||||||
rpcbindOpt: Option[String],
|
rpcbindOpt: Option[String],
|
||||||
rpcport: Int,
|
rpcport: Int,
|
||||||
rpcPassword: String,
|
rpcPassword: String,
|
||||||
@ -86,29 +93,64 @@ case class Server(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val serverCmdDirective: FromRequestUnmarshaller[ServerCommand] =
|
||||||
|
MarshallingDirectives.as[ServerCommand]
|
||||||
|
|
||||||
|
private val initF =
|
||||||
|
Future.successful(PartialFunction.empty[ServerCommand, Route])
|
||||||
|
|
||||||
|
private def handlerF: Future[PartialFunction[ServerCommand, Route]] = {
|
||||||
|
handlersF.foldLeft(initF) { case (accumF, currF) =>
|
||||||
|
for {
|
||||||
|
accum <- accumF
|
||||||
|
newAccum <-
|
||||||
|
if (currF.isCompleted) {
|
||||||
|
currF.map(curr => accum.orElse(curr.handleCommand))
|
||||||
|
} else {
|
||||||
|
Future.successful(accum)
|
||||||
|
}
|
||||||
|
} yield {
|
||||||
|
newAccum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val route: Route = {
|
val route: Route = {
|
||||||
|
|
||||||
val commonRoute = withErrorHandling {
|
val commonRoute: Route = {
|
||||||
pathSingleSlash {
|
withErrorHandling {
|
||||||
post {
|
PathDirectives.pathSingleSlash {
|
||||||
entity(as[ServerCommand]) { cmd =>
|
MethodDirectives.post { ctx =>
|
||||||
val init = PartialFunction.empty[ServerCommand, Route]
|
val route: Future[Route] = {
|
||||||
val handler = handlers.foldLeft(init) { case (accum, curr) =>
|
for {
|
||||||
accum.orElse(curr.handleCommand)
|
handler <- handlerF
|
||||||
|
} yield {
|
||||||
|
MarshallingDirectives.entity(serverCmdDirective) { cmd =>
|
||||||
|
val i = handler.orElse(catchAllHandler).apply(cmd)
|
||||||
|
i
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handler.orElse(catchAllHandler).apply(cmd)
|
route.flatMap(_.apply(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val authenticatedRoute = if (rpcPassword.isEmpty) {
|
val authDirectiveOpt: Option[Directive1[Done]] = {
|
||||||
commonRoute
|
if (rpcPassword.isEmpty) {
|
||||||
} else {
|
None
|
||||||
authenticateBasic("auth", authenticator) { _ =>
|
} else {
|
||||||
commonRoute
|
Some(authenticateBasic("auth", authenticator))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val authenticatedRoute: Route = authDirectiveOpt match {
|
||||||
|
case Some(authDirective) =>
|
||||||
|
authDirective { case _ =>
|
||||||
|
commonRoute
|
||||||
|
}
|
||||||
|
case None => commonRoute
|
||||||
|
}
|
||||||
|
|
||||||
DebuggingDirectives.logRequestResult(
|
DebuggingDirectives.logRequestResult(
|
||||||
("http-rpc-server", Logging.DebugLevel)) {
|
("http-rpc-server", Logging.DebugLevel)) {
|
||||||
@ -117,10 +159,12 @@ case class Server(
|
|||||||
}
|
}
|
||||||
|
|
||||||
def start(): Future[ServerBindings] = {
|
def start(): Future[ServerBindings] = {
|
||||||
val httpFut =
|
val httpFut = for {
|
||||||
Http()
|
http <- Http()
|
||||||
.newServerAt(rpchost, rpcport)
|
.newServerAt(rpchost, rpcport)
|
||||||
.bindFlow(route)
|
.bindFlow(route)
|
||||||
|
} yield http
|
||||||
|
|
||||||
httpFut.foreach { http =>
|
httpFut.foreach { http =>
|
||||||
logger.info(s"Started Bitcoin-S HTTP server at ${http.localAddress}")
|
logger.info(s"Started Bitcoin-S HTTP server at ${http.localAddress}")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.bitcoins.server.util
|
||||||
|
|
||||||
|
import scala.concurrent.Future
|
||||||
|
|
||||||
|
/** A trait used to indicated when different parts of [[BitcoinSAppConfig]] are started */
|
||||||
|
sealed trait AppConfigMarker
|
||||||
|
|
||||||
|
/** This class represents when BitcoinSAppConfig modules are started
|
||||||
|
* @param torStartedF this future is completed when all tor dependent modules are fully started
|
||||||
|
* the reason this is needed is because tor startup time is so variable
|
||||||
|
* @see https://github.com/bitcoin-s/bitcoin-s/issues/4210
|
||||||
|
*/
|
||||||
|
case class StartedBitcoinSAppConfig(torStartedF: Future[Unit])
|
||||||
|
extends AppConfigMarker
|
||||||
|
|
||||||
|
case object StoppedBitcoinSAppConfig extends AppConfigMarker
|
@ -67,7 +67,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
|||||||
|
|
||||||
val mockNode = mock[Node]
|
val mockNode = mock[Node]
|
||||||
|
|
||||||
val chainRoutes = ChainRoutes(mockChainApi, RegTest)
|
val chainRoutes = ChainRoutes(mockChainApi, RegTest, Future.unit)
|
||||||
|
|
||||||
val nodeRoutes = NodeRoutes(mockNode)
|
val nodeRoutes = NodeRoutes(mockNode)
|
||||||
|
|
||||||
|
@ -13,6 +13,11 @@ import org.bitcoins.dlc.wallet.DLCAppConfig
|
|||||||
import org.bitcoins.keymanager.config.KeyManagerAppConfig
|
import org.bitcoins.keymanager.config.KeyManagerAppConfig
|
||||||
import org.bitcoins.node.config.NodeAppConfig
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
import org.bitcoins.rpc.config.BitcoindRpcAppConfig
|
import org.bitcoins.rpc.config.BitcoindRpcAppConfig
|
||||||
|
import org.bitcoins.server.util.{
|
||||||
|
AppConfigMarker,
|
||||||
|
StartedBitcoinSAppConfig,
|
||||||
|
StoppedBitcoinSAppConfig
|
||||||
|
}
|
||||||
import org.bitcoins.tor.config.TorAppConfig
|
import org.bitcoins.tor.config.TorAppConfig
|
||||||
import org.bitcoins.wallet.config.WalletAppConfig
|
import org.bitcoins.wallet.config.WalletAppConfig
|
||||||
|
|
||||||
@ -33,7 +38,7 @@ import scala.concurrent.duration.{DurationInt, FiniteDuration}
|
|||||||
case class BitcoinSAppConfig(
|
case class BitcoinSAppConfig(
|
||||||
baseDatadir: Path,
|
baseDatadir: Path,
|
||||||
configOverrides: Vector[Config])(implicit system: ActorSystem)
|
configOverrides: Vector[Config])(implicit system: ActorSystem)
|
||||||
extends StartStopAsync[Unit]
|
extends StartStopAsync[AppConfigMarker]
|
||||||
with Logging {
|
with Logging {
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
|
|
||||||
@ -65,7 +70,7 @@ case class BitcoinSAppConfig(
|
|||||||
lazy val network: NetworkParameters = chainConf.network
|
lazy val network: NetworkParameters = chainConf.network
|
||||||
|
|
||||||
/** Initializes the wallet, node and chain projects */
|
/** Initializes the wallet, node and chain projects */
|
||||||
override def start(): Future[Unit] = {
|
override def start(): Future[StartedBitcoinSAppConfig] = {
|
||||||
val start = TimeUtil.currentEpochMs
|
val start = TimeUtil.currentEpochMs
|
||||||
//configurations that don't depend on tor startup
|
//configurations that don't depend on tor startup
|
||||||
//start these in parallel as an optimization
|
//start these in parallel as an optimization
|
||||||
@ -83,22 +88,23 @@ case class BitcoinSAppConfig(
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
_ <- startedNonTorConfigs
|
_ <- startedNonTorConfigs
|
||||||
_ <- startedTorDependentConfigsF
|
|
||||||
} yield {
|
} yield {
|
||||||
logger.info(
|
logger.info(
|
||||||
s"Done starting BitcoinSAppConfig, it took=${TimeUtil.currentEpochMs - start}ms")
|
s"Done starting BitcoinSAppConfig, it took=${TimeUtil.currentEpochMs - start}ms")
|
||||||
()
|
StartedBitcoinSAppConfig(startedTorDependentConfigsF.map(_ => ()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def stop(): Future[Unit] = {
|
override def stop(): Future[StoppedBitcoinSAppConfig.type] = {
|
||||||
for {
|
for {
|
||||||
_ <- nodeConf.stop()
|
_ <- nodeConf.stop()
|
||||||
_ <- walletConf.stop()
|
_ <- walletConf.stop()
|
||||||
_ <- chainConf.stop()
|
_ <- chainConf.stop()
|
||||||
_ <- bitcoindRpcConf.stop()
|
_ <- bitcoindRpcConf.stop()
|
||||||
_ <- torConf.stop()
|
_ <- torConf.stop()
|
||||||
} yield ()
|
} yield {
|
||||||
|
StoppedBitcoinSAppConfig
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The underlying config the result of our fields derive from */
|
/** The underlying config the result of our fields derive from */
|
||||||
|
@ -77,13 +77,13 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_ <- startedConfigF
|
startedConfig <- startedConfigF
|
||||||
start <- {
|
start <- {
|
||||||
nodeConf.nodeType match {
|
nodeConf.nodeType match {
|
||||||
case _: InternalImplementationNodeType =>
|
case _: InternalImplementationNodeType =>
|
||||||
startBitcoinSBackend()
|
startBitcoinSBackend(startedConfig.torStartedF)
|
||||||
case NodeType.BitcoindBackend =>
|
case NodeType.BitcoindBackend =>
|
||||||
startBitcoindBackend()
|
startBitcoindBackend(startedConfig.torStartedF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} yield {
|
} yield {
|
||||||
@ -107,7 +107,11 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def startBitcoinSBackend(): Future[Unit] = {
|
/** Start the bitcoin-s wallet server with a neutrino backend
|
||||||
|
* @param startedTorConfigF a future that is completed when tor is fully started
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
def startBitcoinSBackend(startedTorConfigF: Future[Unit]): Future[Unit] = {
|
||||||
logger.info(s"startBitcoinSBackend()")
|
logger.info(s"startBitcoinSBackend()")
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
|
|
||||||
@ -174,27 +178,29 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
val startedDLCNodeF = dlcNodeF
|
val startedDLCNodeF = dlcNodeF
|
||||||
.flatMap(_.start())
|
.flatMap(_.start())
|
||||||
.flatMap(_ => dlcNodeF)
|
.flatMap(_ => dlcNodeF)
|
||||||
|
|
||||||
|
val chainApi = ChainHandler.fromDatabase()
|
||||||
//start our http server now that we are synced
|
//start our http server now that we are synced
|
||||||
for {
|
for {
|
||||||
wallet <- configuredWalletF
|
_ <- startHttpServer(
|
||||||
node <- startedNodeF
|
nodeApiF = startedNodeF,
|
||||||
_ <- startedWalletF
|
chainApi = chainApi,
|
||||||
cachedChainApi <- node.chainApiFromDb()
|
walletF = configuredWalletF,
|
||||||
chainApi = ChainHandler.fromChainHandlerCached(cachedChainApi)
|
dlcNodeF = startedDLCNodeF,
|
||||||
dlcNode <- startedDLCNodeF
|
torConfStarted = startedTorConfigF,
|
||||||
_ <- startHttpServer(nodeApi = node,
|
serverCmdLineArgs = serverArgParser,
|
||||||
chainApi = chainApi,
|
wsSource = wsSource
|
||||||
wallet = wallet,
|
)
|
||||||
dlcNode = dlcNode,
|
|
||||||
serverCmdLineArgs = serverArgParser,
|
|
||||||
wsSource = wsSource)
|
|
||||||
_ = {
|
_ = {
|
||||||
logger.info(
|
logger.info(
|
||||||
s"Starting ${nodeConf.nodeType.shortName} node sync, it took=${System
|
s"Starting ${nodeConf.nodeType.shortName} node sync, it took=${System
|
||||||
.currentTimeMillis() - start}ms")
|
.currentTimeMillis() - start}ms")
|
||||||
}
|
}
|
||||||
|
_ <- startedWalletF
|
||||||
//make sure callbacks are registered before we start sync
|
//make sure callbacks are registered before we start sync
|
||||||
_ <- callbacksF
|
_ <- callbacksF
|
||||||
|
node <- startedNodeF
|
||||||
|
_ <- startedTorConfigF
|
||||||
_ <- node.sync()
|
_ <- node.sync()
|
||||||
} yield {
|
} yield {
|
||||||
logger.info(
|
logger.info(
|
||||||
@ -235,14 +241,22 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
} yield info
|
} yield info
|
||||||
}
|
}
|
||||||
|
|
||||||
def startBitcoindBackend(): Future[Unit] = {
|
/** Start the bitcoin-s wallet server with a bitcoind backend
|
||||||
|
* @param startedTorConfigF a future that is completed when tor is fully started
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
def startBitcoindBackend(startedTorConfigF: Future[Unit]): Future[Unit] = {
|
||||||
logger.info(s"startBitcoindBackend()")
|
logger.info(s"startBitcoindBackend()")
|
||||||
val bitcoindF = for {
|
val bitcoindF = for {
|
||||||
client <- bitcoindRpcConf.clientF
|
client <- bitcoindRpcConf.clientF
|
||||||
_ <- client.start()
|
_ <- client.start()
|
||||||
} yield client
|
} yield client
|
||||||
|
|
||||||
val tmpWalletF = bitcoindF.flatMap { bitcoind =>
|
val tuple = buildWsSource
|
||||||
|
val wsQueue: SourceQueueWithComplete[Message] = tuple._1
|
||||||
|
val wsSource: Source[Message, NotUsed] = tuple._2
|
||||||
|
|
||||||
|
val walletF = bitcoindF.flatMap { bitcoind =>
|
||||||
val feeProvider = FeeProviderFactory.getFeeProviderOrElse(
|
val feeProvider = FeeProviderFactory.getFeeProviderOrElse(
|
||||||
bitcoind,
|
bitcoind,
|
||||||
feeProviderNameStrOpt = walletConf.feeProviderNameOpt,
|
feeProviderNameStrOpt = walletConf.feeProviderNameOpt,
|
||||||
@ -250,14 +264,38 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
proxyParamsOpt = walletConf.torConf.socks5ProxyParams,
|
proxyParamsOpt = walletConf.torConf.socks5ProxyParams,
|
||||||
network = walletConf.network
|
network = walletConf.network
|
||||||
)
|
)
|
||||||
dlcConf.createDLCWallet(nodeApi = bitcoind,
|
logger.info("Creating wallet")
|
||||||
chainQueryApi = bitcoind,
|
val tmpWalletF = dlcConf.createDLCWallet(nodeApi = bitcoind,
|
||||||
feeRateApi = feeProvider)
|
chainQueryApi = bitcoind,
|
||||||
|
feeRateApi = feeProvider)
|
||||||
|
val chainCallbacks = WebsocketUtil.buildChainCallbacks(wsQueue, bitcoind)
|
||||||
|
for {
|
||||||
|
tmpWallet <- tmpWalletF
|
||||||
|
wallet = BitcoindRpcBackendUtil.createDLCWalletWithBitcoindCallbacks(
|
||||||
|
bitcoind,
|
||||||
|
tmpWallet,
|
||||||
|
Some(chainCallbacks))
|
||||||
|
nodeCallbacks <- CallbackUtil.createBitcoindNodeCallbacksForWallet(
|
||||||
|
wallet)
|
||||||
|
_ = nodeConf.addCallbacks(nodeCallbacks)
|
||||||
|
_ = logger.info("Starting wallet")
|
||||||
|
_ <- wallet.start().recoverWith {
|
||||||
|
//https://github.com/bitcoin-s/bitcoin-s/issues/2917
|
||||||
|
//https://github.com/bitcoin-s/bitcoin-s/pull/2918
|
||||||
|
case err: IllegalArgumentException
|
||||||
|
if err.getMessage.contains("If we have spent a spendinginfodb") =>
|
||||||
|
handleMissingSpendingInfoDb(err, wallet)
|
||||||
|
}
|
||||||
|
} yield wallet
|
||||||
}
|
}
|
||||||
|
|
||||||
val tuple = buildWsSource
|
val dlcNodeF = {
|
||||||
val wsQueue: SourceQueueWithComplete[Message] = tuple._1
|
for {
|
||||||
val wsSource: Source[Message, NotUsed] = tuple._2
|
wallet <- walletF
|
||||||
|
dlcNode = dlcNodeConf.createDLCNode(wallet)
|
||||||
|
_ <- dlcNode.start()
|
||||||
|
} yield dlcNode
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_ <- bitcoindRpcConf.start()
|
_ <- bitcoindRpcConf.start()
|
||||||
@ -268,42 +306,26 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
_ = require(
|
_ = require(
|
||||||
bitcoindNetwork == walletConf.network,
|
bitcoindNetwork == walletConf.network,
|
||||||
s"bitcoind ($bitcoindNetwork) on different network than wallet (${walletConf.network})")
|
s"bitcoind ($bitcoindNetwork) on different network than wallet (${walletConf.network})")
|
||||||
|
_ <- startHttpServer(
|
||||||
_ = logger.info("Creating wallet")
|
nodeApiF = Future.successful(bitcoind),
|
||||||
chainCallbacks = WebsocketUtil.buildChainCallbacks(wsQueue, bitcoind)
|
chainApi = bitcoind,
|
||||||
tmpWallet <- tmpWalletF
|
walletF = walletF,
|
||||||
wallet = BitcoindRpcBackendUtil.createDLCWalletWithBitcoindCallbacks(
|
dlcNodeF = dlcNodeF,
|
||||||
bitcoind,
|
torConfStarted = startedTorConfigF,
|
||||||
tmpWallet,
|
serverCmdLineArgs = serverArgParser,
|
||||||
Some(chainCallbacks))
|
wsSource = wsSource
|
||||||
nodeCallbacks <- CallbackUtil.createBitcoindNodeCallbacksForWallet(wallet)
|
)
|
||||||
_ = nodeConf.addCallbacks(nodeCallbacks)
|
|
||||||
_ = logger.info("Starting wallet")
|
|
||||||
_ <- wallet.start().recoverWith {
|
|
||||||
//https://github.com/bitcoin-s/bitcoin-s/issues/2917
|
|
||||||
//https://github.com/bitcoin-s/bitcoin-s/pull/2918
|
|
||||||
case err: IllegalArgumentException
|
|
||||||
if err.getMessage.contains("If we have spent a spendinginfodb") =>
|
|
||||||
handleMissingSpendingInfoDb(err, wallet)
|
|
||||||
}
|
|
||||||
|
|
||||||
dlcNode = dlcNodeConf.createDLCNode(wallet)
|
|
||||||
_ <- dlcNode.start()
|
|
||||||
_ <- startHttpServer(nodeApi = bitcoind,
|
|
||||||
chainApi = bitcoind,
|
|
||||||
wallet = wallet,
|
|
||||||
dlcNode = dlcNode,
|
|
||||||
serverCmdLineArgs = serverArgParser,
|
|
||||||
wsSource = wsSource)
|
|
||||||
walletCallbacks = WebsocketUtil.buildWalletCallbacks(wsQueue)
|
walletCallbacks = WebsocketUtil.buildWalletCallbacks(wsQueue)
|
||||||
_ = walletConf.addCallbacks(walletCallbacks)
|
_ = walletConf.addCallbacks(walletCallbacks)
|
||||||
|
|
||||||
|
wallet <- walletF
|
||||||
//intentionally doesn't map on this otherwise we
|
//intentionally doesn't map on this otherwise we
|
||||||
//wait until we are done syncing the entire wallet
|
//wait until we are done syncing the entire wallet
|
||||||
//which could take 1 hour
|
//which could take 1 hour
|
||||||
_ = syncWalletWithBitcoindAndStartPolling(bitcoind, wallet)
|
_ = syncWalletWithBitcoindAndStartPolling(bitcoind, wallet)
|
||||||
dlcWalletCallbacks = WebsocketUtil.buildDLCWalletCallbacks(wsQueue)
|
dlcWalletCallbacks = WebsocketUtil.buildDLCWalletCallbacks(wsQueue)
|
||||||
_ = dlcConf.addCallbacks(dlcWalletCallbacks)
|
_ = dlcConf.addCallbacks(dlcWalletCallbacks)
|
||||||
|
_ <- startedTorConfigF
|
||||||
} yield {
|
} yield {
|
||||||
logger.info(s"Done starting Main!")
|
logger.info(s"Done starting Main!")
|
||||||
()
|
()
|
||||||
@ -351,10 +373,11 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
private var serverBindingsOpt: Option[ServerBindings] = None
|
private var serverBindingsOpt: Option[ServerBindings] = None
|
||||||
|
|
||||||
private def startHttpServer(
|
private def startHttpServer(
|
||||||
nodeApi: NodeApi,
|
nodeApiF: Future[NodeApi],
|
||||||
chainApi: ChainApi,
|
chainApi: ChainApi,
|
||||||
wallet: DLCWallet,
|
walletF: Future[DLCWallet],
|
||||||
dlcNode: DLCNode,
|
dlcNodeF: Future[DLCNode],
|
||||||
|
torConfStarted: Future[Unit],
|
||||||
serverCmdLineArgs: ServerArgParser,
|
serverCmdLineArgs: ServerArgParser,
|
||||||
wsSource: Source[Message, NotUsed])(implicit
|
wsSource: Source[Message, NotUsed])(implicit
|
||||||
system: ActorSystem,
|
system: ActorSystem,
|
||||||
@ -362,20 +385,21 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
implicit val nodeConf: NodeAppConfig = conf.nodeConf
|
implicit val nodeConf: NodeAppConfig = conf.nodeConf
|
||||||
implicit val walletConf: WalletAppConfig = conf.walletConf
|
implicit val walletConf: WalletAppConfig = conf.walletConf
|
||||||
|
|
||||||
val walletRoutes = WalletRoutes(wallet)
|
val walletRoutesF = walletF.map(WalletRoutes(_))
|
||||||
val nodeRoutes = NodeRoutes(nodeApi)
|
val nodeRoutesF = nodeApiF.map(NodeRoutes(_))
|
||||||
val chainRoutes = ChainRoutes(chainApi, nodeConf.network)
|
val chainRoutes =
|
||||||
|
ChainRoutes(chainApi, nodeConf.network, torConfStarted)
|
||||||
val coreRoutes = CoreRoutes()
|
val coreRoutes = CoreRoutes()
|
||||||
val dlcRoutes = DLCRoutes(dlcNode)
|
val dlcRoutesF = dlcNodeF.map(DLCRoutes(_))
|
||||||
val commonRoutes = CommonRoutes(conf.baseDatadir)
|
val commonRoutes = CommonRoutes(conf.baseDatadir)
|
||||||
|
|
||||||
val handlers =
|
val handlers =
|
||||||
Seq(walletRoutes,
|
Seq(walletRoutesF,
|
||||||
nodeRoutes,
|
nodeRoutesF,
|
||||||
chainRoutes,
|
Future.successful(chainRoutes),
|
||||||
coreRoutes,
|
Future.successful(coreRoutes),
|
||||||
dlcRoutes,
|
dlcRoutesF,
|
||||||
commonRoutes)
|
Future.successful(commonRoutes))
|
||||||
|
|
||||||
val rpcBindConfOpt = serverCmdLineArgs.rpcBindOpt match {
|
val rpcBindConfOpt = serverCmdLineArgs.rpcBindOpt match {
|
||||||
case Some(rpcbind) => Some(rpcbind)
|
case Some(rpcbind) => Some(rpcbind)
|
||||||
@ -399,7 +423,7 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
serverCmdLineArgs.rpcPortOpt match {
|
serverCmdLineArgs.rpcPortOpt match {
|
||||||
case Some(rpcport) =>
|
case Some(rpcport) =>
|
||||||
Server(conf = nodeConf,
|
Server(conf = nodeConf,
|
||||||
handlers = handlers,
|
handlersF = handlers,
|
||||||
rpcbindOpt = rpcBindConfOpt,
|
rpcbindOpt = rpcBindConfOpt,
|
||||||
rpcport = rpcport,
|
rpcport = rpcport,
|
||||||
rpcPassword = conf.rpcPassword,
|
rpcPassword = conf.rpcPassword,
|
||||||
@ -408,7 +432,7 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
|||||||
case None =>
|
case None =>
|
||||||
Server(
|
Server(
|
||||||
conf = nodeConf,
|
conf = nodeConf,
|
||||||
handlers = handlers,
|
handlersF = handlers,
|
||||||
rpcbindOpt = rpcBindConfOpt,
|
rpcbindOpt = rpcBindConfOpt,
|
||||||
rpcport = conf.rpcPort,
|
rpcport = conf.rpcPort,
|
||||||
rpcPassword = conf.rpcPassword,
|
rpcPassword = conf.rpcPassword,
|
||||||
|
@ -13,8 +13,10 @@ import org.bitcoins.server.util.ChainUtil
|
|||||||
|
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
|
|
||||||
case class ChainRoutes(chain: ChainApi, network: BitcoinNetwork)(implicit
|
case class ChainRoutes(
|
||||||
system: ActorSystem)
|
chain: ChainApi,
|
||||||
|
network: BitcoinNetwork,
|
||||||
|
startedTorConfigF: Future[Unit])(implicit system: ActorSystem)
|
||||||
extends ServerRoute {
|
extends ServerRoute {
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
|
|
||||||
@ -67,7 +69,11 @@ case class ChainRoutes(chain: ChainApi, network: BitcoinNetwork)(implicit
|
|||||||
case ServerCommand("getinfo", _) =>
|
case ServerCommand("getinfo", _) =>
|
||||||
complete {
|
complete {
|
||||||
chain.getBestBlockHeader().map { header =>
|
chain.getBestBlockHeader().map { header =>
|
||||||
val info = BitcoinSServerInfo(network, header.height, header.hashBE)
|
val info = BitcoinSServerInfo(network = network,
|
||||||
|
blockHeight = header.height,
|
||||||
|
blockHash = header.hashBE,
|
||||||
|
torStarted =
|
||||||
|
startedTorConfigF.isCompleted)
|
||||||
|
|
||||||
Server.httpSuccess(info.toJson)
|
Server.httpSuccess(info.toJson)
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ object PicklerKeys {
|
|||||||
final val chainworkKey: String = "chainwork"
|
final val chainworkKey: String = "chainwork"
|
||||||
final val previousblockhashKey: String = "previousblockhash"
|
final val previousblockhashKey: String = "previousblockhash"
|
||||||
final val nextblockhashKey: String = "nextblockhash"
|
final val nextblockhashKey: String = "nextblockhash"
|
||||||
|
final val blockHashKey: String = "blockHash"
|
||||||
|
final val blockHeightKey: String = "blockHeight"
|
||||||
final val myCollateral: String = "myCollateral"
|
final val myCollateral: String = "myCollateral"
|
||||||
final val theirCollateral: String = "theirCollateral"
|
final val theirCollateral: String = "theirCollateral"
|
||||||
final val myPayout: String = "myPayout"
|
final val myPayout: String = "myPayout"
|
||||||
@ -39,10 +41,14 @@ object PicklerKeys {
|
|||||||
final val pnl: String = "pnl"
|
final val pnl: String = "pnl"
|
||||||
final val rateOfReturn: String = "rateOfReturn"
|
final val rateOfReturn: String = "rateOfReturn"
|
||||||
|
|
||||||
|
final val networkKey: String = "network"
|
||||||
|
|
||||||
final val outcomeKey: String = "outcome"
|
final val outcomeKey: String = "outcome"
|
||||||
final val localPayoutKey: String = "localPayout"
|
final val localPayoutKey: String = "localPayout"
|
||||||
final val outcomesKey: String = "outcomes"
|
final val outcomesKey: String = "outcomes"
|
||||||
|
|
||||||
|
final val torStartedKey: String = "torStarted"
|
||||||
|
|
||||||
//tlv points
|
//tlv points
|
||||||
final val pointsKey = "points"
|
final val pointsKey = "points"
|
||||||
final val payoutKey: String = "payout"
|
final val payoutKey: String = "payout"
|
||||||
|
@ -39,6 +39,7 @@ trait CachedBitcoinSAppConfig { _: BitcoinSAkkaAsyncTest =>
|
|||||||
|
|
||||||
override def afterAll(): Unit = {
|
override def afterAll(): Unit = {
|
||||||
Await.result(cachedConfig.stop(), duration)
|
Await.result(cachedConfig.stop(), duration)
|
||||||
|
()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user