mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
Get both bundle and app server logging working (#3362)
* Get both bundle and app server logging working, oracleServer does not compile * Get everythig compiling * Fix bug where bundle wouldn't use command line param rpc port for ConsoleCli * Add unit tests to make sure we are translating to config properly * Fix bug where app config wasn't re-created after parsing bundle args * Fix datadir resolution in BundleGUI * Implement force-recalc-chainwork * fix bug * Try not using tilde on windows * Try to print datadir on CI * Try using stackoverflow answer * Try escaping windows path * Take ben's suggestion of using AppConfig.safePathToString * Just check the paths are equal * Fix nullpointerexceptions on startup * Fix bug where bitcoin-s-bundle.conf was not being read * Remove usage of --conf flag in bundle when starting backend server * Fix compile * Rename usedDir -> networkDir * Fix passing in datadir
This commit is contained in:
parent
5df7a8bdf3
commit
bc79a24f53
@ -1,12 +1,10 @@
|
|||||||
package org.bitcoins.bundle.gui
|
package org.bitcoins.bundle.gui
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import org.bitcoins.bundle.util.BitcoinSAppJFX3
|
||||||
import com.typesafe.config.Config
|
import org.bitcoins.db.util.{DatadirParser, ServerArgParser}
|
||||||
import org.bitcoins.db.AppConfig
|
|
||||||
import org.bitcoins.db.AppConfig.DEFAULT_BITCOIN_S_DATADIR
|
|
||||||
import org.bitcoins.gui._
|
import org.bitcoins.gui._
|
||||||
import org.bitcoins.gui.util.GUIUtil
|
import org.bitcoins.gui.util.GUIUtil
|
||||||
import org.bitcoins.server.util.DatadirUtil
|
import org.bitcoins.server.BitcoinSAppConfig
|
||||||
import scalafx.application.{JFXApp3, Platform}
|
import scalafx.application.{JFXApp3, Platform}
|
||||||
import scalafx.geometry.Pos
|
import scalafx.geometry.Pos
|
||||||
import scalafx.scene.Scene
|
import scalafx.scene.Scene
|
||||||
@ -14,14 +12,14 @@ import scalafx.scene.control.Alert.AlertType
|
|||||||
import scalafx.scene.control._
|
import scalafx.scene.control._
|
||||||
import scalafx.scene.layout.VBox
|
import scalafx.scene.layout.VBox
|
||||||
|
|
||||||
import java.nio.file.{Path, Paths}
|
object BundleGUI extends WalletGUI with BitcoinSAppJFX3 {
|
||||||
|
|
||||||
object BundleGUI extends WalletGUI with JFXApp3 {
|
override val customFinalDirOpt: Option[String] = None
|
||||||
|
|
||||||
implicit override lazy val system: ActorSystem = ActorSystem(
|
override val actorSystemName: String =
|
||||||
s"bitcoin-s-gui-${System.currentTimeMillis()}")
|
s"bitcoin-s-gui-${System.currentTimeMillis()}"
|
||||||
|
|
||||||
lazy val args = parameters.raw
|
override lazy val commandLineArgs: Array[String] = parameters.raw.toArray
|
||||||
|
|
||||||
override def start(): Unit = {
|
override def start(): Unit = {
|
||||||
// Catch unhandled exceptions on FX Application thread
|
// Catch unhandled exceptions on FX Application thread
|
||||||
@ -37,19 +35,26 @@ object BundleGUI extends WalletGUI with JFXApp3 {
|
|||||||
}.showAndWait()
|
}.showAndWait()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set log location
|
lazy val serverArgParser = ServerArgParser(commandLineArgs.toVector)
|
||||||
val baseConfig: Config = AppConfig
|
|
||||||
.getBaseConfig(DEFAULT_BITCOIN_S_DATADIR)
|
|
||||||
.resolve()
|
|
||||||
|
|
||||||
val datadir: Path =
|
val datadirParser = DatadirParser(serverArgParser, customFinalDirOpt)
|
||||||
Paths.get(baseConfig.getString("bitcoin-s.datadir"))
|
|
||||||
|
|
||||||
val usedDir = DatadirUtil.getFinalDatadir(datadir, baseConfig, None)
|
System.setProperty("bitcoins.log.location",
|
||||||
|
datadirParser.networkDir.toAbsolutePath.toString)
|
||||||
|
|
||||||
System.setProperty("bitcoins.log.location", usedDir.toAbsolutePath.toString)
|
//adjust the rpc port if one was specified
|
||||||
|
GlobalData.rpcPortOpt = serverArgParser.rpcPortOpt match {
|
||||||
|
case Some(rpcPort) => Some(rpcPort)
|
||||||
|
case None => GlobalData.rpcPortOpt //keep previous setting
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit val appConfig: BitcoinSAppConfig =
|
||||||
|
BitcoinSAppConfig.fromDatadirWithBundleConfWithServerArgs(
|
||||||
|
datadirParser.datadir,
|
||||||
|
serverArgParser)(system.dispatcher)
|
||||||
|
|
||||||
|
val landingPane = new LandingPane(glassPane, serverArgParser)
|
||||||
|
|
||||||
val landingPane = new LandingPane(glassPane)
|
|
||||||
rootView.children = Vector(landingPane.view, glassPane)
|
rootView.children = Vector(landingPane.view, glassPane)
|
||||||
|
|
||||||
lazy val guiScene: Scene = new Scene(1400, 600) {
|
lazy val guiScene: Scene = new Scene(1400, 600) {
|
||||||
|
@ -2,6 +2,7 @@ package org.bitcoins.bundle.gui
|
|||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
import grizzled.slf4j.Logging
|
import grizzled.slf4j.Logging
|
||||||
|
import org.bitcoins.db.util.ServerArgParser
|
||||||
import org.bitcoins.gui._
|
import org.bitcoins.gui._
|
||||||
import org.bitcoins.node.NodeType
|
import org.bitcoins.node.NodeType
|
||||||
import org.bitcoins.server.BitcoinSAppConfig
|
import org.bitcoins.server.BitcoinSAppConfig
|
||||||
@ -13,15 +14,12 @@ import scalafx.scene.text._
|
|||||||
|
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
|
|
||||||
class LandingPane(glassPane: VBox)(implicit system: ActorSystem)
|
class LandingPane(glassPane: VBox, serverArgParser: ServerArgParser)(implicit
|
||||||
|
system: ActorSystem,
|
||||||
|
appConfig: BitcoinSAppConfig)
|
||||||
extends Logging {
|
extends Logging {
|
||||||
|
|
||||||
import system.dispatcher
|
val model = new LandingPaneModel(serverArgParser)
|
||||||
|
|
||||||
val appConfig: BitcoinSAppConfig =
|
|
||||||
BitcoinSAppConfig.fromDefaultDatadirWithBundleConf()
|
|
||||||
|
|
||||||
val model = new LandingPaneModel()
|
|
||||||
|
|
||||||
private val label: Label = new Label("Welcome to Bitcoin-S") {
|
private val label: Label = new Label("Welcome to Bitcoin-S") {
|
||||||
alignmentInParent = Pos.BottomCenter
|
alignmentInParent = Pos.BottomCenter
|
||||||
|
@ -5,20 +5,22 @@ import com.typesafe.config._
|
|||||||
import grizzled.slf4j.Logging
|
import grizzled.slf4j.Logging
|
||||||
import org.bitcoins.bundle.gui.BundleGUI._
|
import org.bitcoins.bundle.gui.BundleGUI._
|
||||||
import org.bitcoins.db.AppConfig
|
import org.bitcoins.db.AppConfig
|
||||||
|
import org.bitcoins.db.util.{DatadirUtil, ServerArgParser}
|
||||||
import org.bitcoins.gui._
|
import org.bitcoins.gui._
|
||||||
import org.bitcoins.node.NodeType._
|
import org.bitcoins.node.NodeType._
|
||||||
import org.bitcoins.node._
|
import org.bitcoins.node._
|
||||||
import org.bitcoins.server.BitcoinSAppConfig.toNodeConf
|
import org.bitcoins.server.BitcoinSAppConfig.toNodeConf
|
||||||
import org.bitcoins.server._
|
import org.bitcoins.server._
|
||||||
import org.bitcoins.server.util.DatadirUtil
|
|
||||||
import scalafx.beans.property.ObjectProperty
|
import scalafx.beans.property.ObjectProperty
|
||||||
import scalafx.stage.Window
|
import scalafx.stage.Window
|
||||||
|
|
||||||
import java.nio.file.{Files, Path}
|
import java.nio.file.Files
|
||||||
import scala.concurrent._
|
import scala.concurrent._
|
||||||
import scala.concurrent.duration.DurationInt
|
import scala.concurrent.duration.DurationInt
|
||||||
|
|
||||||
class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
|
class LandingPaneModel(serverArgParser: ServerArgParser)(implicit
|
||||||
|
system: ActorSystem)
|
||||||
|
extends Logging {
|
||||||
|
|
||||||
var taskRunner: TaskRunner = _
|
var taskRunner: TaskRunner = _
|
||||||
|
|
||||||
@ -40,13 +42,11 @@ class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
|
|||||||
logger.info(s"Writing bundle config to $file")
|
logger.info(s"Writing bundle config to $file")
|
||||||
Files.write(file, bundleConfStr.getBytes)
|
Files.write(file, bundleConfStr.getBytes)
|
||||||
|
|
||||||
val tmpFile = Files.createTempFile("bitcoin-s-tmp-config", ".conf")
|
val networkConfigF: Future[Config] = {
|
||||||
|
|
||||||
val finalConfF: Future[Path] = {
|
|
||||||
val tmpConf =
|
val tmpConf =
|
||||||
BitcoinSAppConfig.fromConfig(
|
BitcoinSAppConfig.fromConfig(
|
||||||
bundleConf.withFallback(appConfig.config))
|
bundleConf.withFallback(appConfig.config))
|
||||||
val netConfF = tmpConf.nodeType match {
|
val netConfF: Future[Config] = tmpConf.nodeType match {
|
||||||
case _: InternalImplementationNodeType =>
|
case _: InternalImplementationNodeType =>
|
||||||
// If we are connecting to a node we cannot
|
// If we are connecting to a node we cannot
|
||||||
// know what network it is on now
|
// know what network it is on now
|
||||||
@ -60,13 +60,9 @@ class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
netConfF.map { netConf =>
|
netConfF.map { netConf =>
|
||||||
val finalConf =
|
serverArgParser.toConfig
|
||||||
BitcoinSAppConfig.fromDefaultDatadirWithBundleConf(
|
.withFallback(netConf)
|
||||||
Vector(netConf, bundleConf))
|
.withFallback(bundleConf)
|
||||||
|
|
||||||
val totalConfStr = AppConfig.configToString(finalConf.config)
|
|
||||||
logger.info(s"Writing resolved config to $tmpFile")
|
|
||||||
Files.write(tmpFile, totalConfStr.getBytes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,11 +74,17 @@ class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
|
|||||||
promise.success(())
|
promise.success(())
|
||||||
}
|
}
|
||||||
|
|
||||||
finalConfF.map { path =>
|
val startedF = networkConfigF.map { networkConfig =>
|
||||||
val extraArgs = Vector("--conf", path.toAbsolutePath.toString)
|
val finalAppConfig =
|
||||||
val usedArgs = extraArgs ++ args
|
BitcoinSAppConfig.fromDatadir(appConfig.baseDatadir, networkConfig)
|
||||||
// use class base constructor to share the actor system
|
// use class base constructor to share the actor system
|
||||||
new BitcoinSServerMain(usedArgs.toArray).run()
|
|
||||||
|
new BitcoinSServerMain(serverArgParser)(system, finalAppConfig)
|
||||||
|
.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
startedF.failed.foreach { case err =>
|
||||||
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
Await.result(promise.future, 60.seconds)
|
Await.result(promise.future, 60.seconds)
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package org.bitcoins.bundle.util
|
||||||
|
|
||||||
|
import org.bitcoins.server.util.BitcoinSApp
|
||||||
|
import scalafx.application.JFXApp3
|
||||||
|
|
||||||
|
trait BitcoinSAppJFX3 extends BitcoinSApp with JFXApp3
|
@ -1,22 +1,21 @@
|
|||||||
package org.bitcoins.oracle.server
|
package org.bitcoins.oracle.server
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
|
import org.bitcoins.db.util.{DatadirParser, ServerArgParser}
|
||||||
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
|
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
|
||||||
import org.bitcoins.server.routes.{BitcoinSRunner, Server}
|
import org.bitcoins.server.routes.{BitcoinSServerRunner, Server}
|
||||||
import org.bitcoins.server.util.BitcoinSApp
|
import org.bitcoins.server.util.BitcoinSAppScalaDaemon
|
||||||
|
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
|
|
||||||
class OracleServerMain(override val args: Array[String])(implicit
|
class OracleServerMain(override val serverArgParser: ServerArgParser)(implicit
|
||||||
override val system: ActorSystem)
|
override val system: ActorSystem,
|
||||||
extends BitcoinSRunner {
|
conf: DLCOracleAppConfig)
|
||||||
|
extends BitcoinSServerRunner {
|
||||||
implicit val conf: DLCOracleAppConfig =
|
|
||||||
DLCOracleAppConfig(datadir, baseConfig)
|
|
||||||
|
|
||||||
override def start(): Future[Unit] = {
|
override def start(): Future[Unit] = {
|
||||||
|
|
||||||
val bindConfOpt = rpcBindOpt match {
|
val bindConfOpt = serverArgParser.rpcBindOpt match {
|
||||||
case Some(rpcbind) => Some(rpcbind)
|
case Some(rpcbind) => Some(rpcbind)
|
||||||
case None => conf.rpcBindOpt
|
case None => conf.rpcBindOpt
|
||||||
}
|
}
|
||||||
@ -26,7 +25,7 @@ class OracleServerMain(override val args: Array[String])(implicit
|
|||||||
oracle <- conf.initialize()
|
oracle <- conf.initialize()
|
||||||
|
|
||||||
routes = Seq(OracleRoutes(oracle))
|
routes = Seq(OracleRoutes(oracle))
|
||||||
server = rpcPortOpt match {
|
server = serverArgParser.rpcPortOpt match {
|
||||||
case Some(rpcport) =>
|
case Some(rpcport) =>
|
||||||
Server(conf = conf,
|
Server(conf = conf,
|
||||||
handlers = routes,
|
handlers = routes,
|
||||||
@ -59,9 +58,24 @@ class OracleServerMain(override val args: Array[String])(implicit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object OracleServerMain extends BitcoinSApp {
|
object OracleServerMain extends BitcoinSAppScalaDaemon {
|
||||||
|
|
||||||
override val actorSystemName =
|
override val actorSystemName =
|
||||||
s"bitcoin-s-oracle-${System.currentTimeMillis()}"
|
s"bitcoin-s-oracle-${System.currentTimeMillis()}"
|
||||||
new OracleServerMain(args).run(Some("oracle"))
|
|
||||||
|
/** Directory specific for current network or custom dir */
|
||||||
|
override val customFinalDirOpt: Option[String] = Some("oracle")
|
||||||
|
|
||||||
|
val serverCmdLineArgs = ServerArgParser(args.toVector)
|
||||||
|
|
||||||
|
val datadirParser =
|
||||||
|
DatadirParser(serverCmdLineArgs, customFinalDirOpt)
|
||||||
|
|
||||||
|
System.setProperty("bitcoins.log.location", datadirParser.networkDir.toString)
|
||||||
|
|
||||||
|
implicit lazy val conf: DLCOracleAppConfig =
|
||||||
|
DLCOracleAppConfig(datadirParser.datadir, datadirParser.baseConfig)(
|
||||||
|
system.dispatcher)
|
||||||
|
|
||||||
|
new OracleServerMain(serverCmdLineArgs).run()
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import org.bitcoins.core.protocol.transaction.WitnessTransaction
|
|||||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||||
import org.bitcoins.server.BitcoindRpcAppConfig
|
import org.bitcoins.server.BitcoindRpcAppConfig
|
||||||
import org.bitcoins.server.routes.BitcoinSRunner
|
import org.bitcoins.server.routes.BitcoinSRunner
|
||||||
import org.bitcoins.server.util.BitcoinSApp
|
import org.bitcoins.server.util.{BitcoinSAppScalaDaemon}
|
||||||
|
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
|
|
||||||
@ -17,13 +17,11 @@ import scala.concurrent.Future
|
|||||||
* between bitcoin-s and bitcoind inside of bitcoin-s.conf
|
* between bitcoin-s and bitcoind inside of bitcoin-s.conf
|
||||||
* @see https://bitcoin-s.org/docs/config/configuration#example-configuration-file
|
* @see https://bitcoin-s.org/docs/config/configuration#example-configuration-file
|
||||||
*/
|
*/
|
||||||
class ScanBitcoind(override val args: Array[String])(implicit
|
class ScanBitcoind()(implicit
|
||||||
override val system: ActorSystem)
|
override val system: ActorSystem,
|
||||||
|
rpcAppConfig: BitcoindRpcAppConfig)
|
||||||
extends BitcoinSRunner {
|
extends BitcoinSRunner {
|
||||||
|
|
||||||
implicit val rpcAppConfig: BitcoindRpcAppConfig =
|
|
||||||
BitcoindRpcAppConfig(datadir, baseConfig)
|
|
||||||
|
|
||||||
override def start(): Future[Unit] = {
|
override def start(): Future[Unit] = {
|
||||||
|
|
||||||
val bitcoind = rpcAppConfig.client
|
val bitcoind = rpcAppConfig.client
|
||||||
@ -96,9 +94,15 @@ class ScanBitcoind(override val args: Array[String])(implicit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ScanBitcoind extends BitcoinSApp {
|
object ScanBitcoind extends BitcoinSAppScalaDaemon {
|
||||||
|
|
||||||
override val actorSystemName: String =
|
override val actorSystemName: String =
|
||||||
s"scan-bitcoind-${System.currentTimeMillis()}"
|
s"scan-bitcoind-${System.currentTimeMillis()}"
|
||||||
new ScanBitcoind(args).run()
|
|
||||||
|
override val customFinalDirOpt = None
|
||||||
|
|
||||||
|
implicit val rpcAppConfig: BitcoindRpcAppConfig =
|
||||||
|
BitcoindRpcAppConfig.fromDefaultDatadir()(system.dispatcher)
|
||||||
|
|
||||||
|
new ScanBitcoind().run()
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
package org.bitcoins.scripts
|
package org.bitcoins.scripts
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
|
import org.bitcoins.db.util.{DatadirParser, ServerArgParser}
|
||||||
import org.bitcoins.server.BitcoinSAppConfig
|
import org.bitcoins.server.BitcoinSAppConfig
|
||||||
import org.bitcoins.server.routes.BitcoinSRunner
|
import org.bitcoins.server.routes.{BitcoinSServerRunner}
|
||||||
import org.bitcoins.server.util.BitcoinSApp
|
import org.bitcoins.server.util.{BitcoinSAppScalaDaemon}
|
||||||
|
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
|
|
||||||
/** This script zips your $HOME/.bitcoin-s/ directory to a specified path, excluding chaindb.sqlite */
|
/** This script zips your $HOME/.bitcoin-s/ directory to a specified path, excluding chaindb.sqlite */
|
||||||
class ZipDatadir(override val args: Array[String])(implicit
|
class ZipDatadir(override val serverArgParser: ServerArgParser)(implicit
|
||||||
override val system: ActorSystem)
|
override val system: ActorSystem,
|
||||||
extends BitcoinSRunner {
|
conf: BitcoinSAppConfig)
|
||||||
|
extends BitcoinSServerRunner {
|
||||||
implicit lazy val conf: BitcoinSAppConfig =
|
|
||||||
BitcoinSAppConfig(datadir, baseConfig)
|
|
||||||
|
|
||||||
override def start(): Future[Unit] = {
|
override def start(): Future[Unit] = {
|
||||||
|
|
||||||
@ -30,9 +29,23 @@ class ZipDatadir(override val args: Array[String])(implicit
|
|||||||
override def stop(): Future[Unit] = Future.unit
|
override def stop(): Future[Unit] = Future.unit
|
||||||
}
|
}
|
||||||
|
|
||||||
object Zip extends BitcoinSApp {
|
object Zip extends BitcoinSAppScalaDaemon {
|
||||||
|
|
||||||
override val actorSystemName: String =
|
override val actorSystemName: String =
|
||||||
s"zip-datadir-${System.currentTimeMillis()}"
|
s"zip-datadir-${System.currentTimeMillis()}"
|
||||||
new ZipDatadir(args).run()
|
|
||||||
|
override val customFinalDirOpt = None
|
||||||
|
|
||||||
|
val serverCmdLineArgs = ServerArgParser(args.toVector)
|
||||||
|
|
||||||
|
val datadirParser =
|
||||||
|
DatadirParser(serverCmdLineArgs, customFinalDirOpt)
|
||||||
|
|
||||||
|
System.setProperty("bitcoins.log.location", datadirParser.networkDir.toString)
|
||||||
|
|
||||||
|
implicit lazy val conf: BitcoinSAppConfig =
|
||||||
|
BitcoinSAppConfig(datadirParser.datadir, datadirParser.baseConfig)(
|
||||||
|
system.dispatcher)
|
||||||
|
|
||||||
|
new ZipDatadir(serverCmdLineArgs).run()
|
||||||
}
|
}
|
||||||
|
@ -1,134 +1,37 @@
|
|||||||
package org.bitcoins.server.routes
|
package org.bitcoins.server.routes
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
import com.typesafe.config.{Config, ConfigFactory}
|
|
||||||
import grizzled.slf4j.Logging
|
import grizzled.slf4j.Logging
|
||||||
import org.bitcoins.core.config._
|
|
||||||
import org.bitcoins.core.util.{EnvUtil, StartStopAsync}
|
import org.bitcoins.core.util.{EnvUtil, StartStopAsync}
|
||||||
import org.bitcoins.db.AppConfig
|
import org.bitcoins.db.util.ServerArgParser
|
||||||
import org.bitcoins.db.AppConfig.safePathToString
|
|
||||||
import org.bitcoins.server.util.DatadirUtil
|
|
||||||
|
|
||||||
import java.nio.file.{Path, Paths}
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
import scala.util.Properties
|
|
||||||
|
|
||||||
trait BitcoinSRunner extends StartStopAsync[Unit] with Logging {
|
trait BitcoinSRunner extends StartStopAsync[Unit] with Logging {
|
||||||
|
|
||||||
protected def args: Array[String]
|
|
||||||
|
|
||||||
implicit def system: ActorSystem
|
implicit def system: ActorSystem
|
||||||
|
|
||||||
implicit lazy val ec: ExecutionContext = system.dispatcher
|
implicit lazy val ec: ExecutionContext = system.dispatcher
|
||||||
|
|
||||||
lazy val argsWithIndex: Vector[(String, Int)] = args.toVector.zipWithIndex
|
|
||||||
|
|
||||||
/** The ip address we are binding the server to */
|
|
||||||
lazy val rpcBindOpt: Option[String] = {
|
|
||||||
val rpcbindOpt = argsWithIndex.find(_._1.toLowerCase == "--rpcbind")
|
|
||||||
rpcbindOpt.map { case (_, idx) =>
|
|
||||||
args(idx + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val rpcPortOpt: Option[Int] = {
|
|
||||||
val portOpt = argsWithIndex.find(_._1.toLowerCase == "--rpcport")
|
|
||||||
portOpt.map { case (_, idx) =>
|
|
||||||
args(idx + 1).toInt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val networkOpt: Option[BitcoinNetwork] = {
|
|
||||||
val netOpt = argsWithIndex.find(_._1.toLowerCase == "--network")
|
|
||||||
netOpt.map { case (_, idx) =>
|
|
||||||
val string = args(idx + 1)
|
|
||||||
string.toLowerCase match {
|
|
||||||
case "mainnet" => MainNet
|
|
||||||
case "main" => MainNet
|
|
||||||
case "testnet3" => TestNet3
|
|
||||||
case "testnet" => TestNet3
|
|
||||||
case "test" => TestNet3
|
|
||||||
case "regtest" => RegTest
|
|
||||||
case "signet" => SigNet
|
|
||||||
case "sig" => SigNet
|
|
||||||
case _: String =>
|
|
||||||
throw new IllegalArgumentException(s"Invalid network $string")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val forceChainWorkRecalc: Boolean =
|
|
||||||
args.exists(_.toLowerCase == "--force-recalc-chainwork")
|
|
||||||
|
|
||||||
private lazy val dataDirIndexOpt: Option[(String, Int)] = {
|
|
||||||
argsWithIndex.find(_._1.toLowerCase == "--datadir")
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the default data dir, overridden by the --datadir option */
|
|
||||||
private lazy val datadirPath: Path = dataDirIndexOpt match {
|
|
||||||
case None => AppConfig.DEFAULT_BITCOIN_S_DATADIR
|
|
||||||
case Some((_, dataDirIndex)) =>
|
|
||||||
val str = args(dataDirIndex + 1)
|
|
||||||
val usableStr = str.replace("~", Properties.userHome)
|
|
||||||
Paths.get(usableStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
private lazy val configIndexOpt: Option[Int] = {
|
|
||||||
argsWithIndex.find(_._1.toLowerCase == "--conf").map(_._2)
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val datadirConfig: Config =
|
|
||||||
ConfigFactory.parseString(
|
|
||||||
s"bitcoin-s.datadir = ${safePathToString(datadirPath)}")
|
|
||||||
|
|
||||||
lazy val networkConfig: Config = networkOpt match {
|
|
||||||
case Some(network) =>
|
|
||||||
val networkStr = DatadirUtil.networkStrToDirName(network.name)
|
|
||||||
ConfigFactory.parseString(s"bitcoin-s.network = $networkStr")
|
|
||||||
case None => ConfigFactory.empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val baseConfig: Config = configIndexOpt match {
|
|
||||||
case None =>
|
|
||||||
AppConfig
|
|
||||||
.getBaseConfig(datadirPath, List(networkConfig))
|
|
||||||
.withFallback(datadirConfig)
|
|
||||||
.resolve()
|
|
||||||
case Some(configIndex) =>
|
|
||||||
val str = args(configIndex + 1)
|
|
||||||
val usableStr = str.replace("~", Properties.userHome)
|
|
||||||
val path = Paths.get(usableStr)
|
|
||||||
val conf = ConfigFactory
|
|
||||||
.parseFile(path.toFile)
|
|
||||||
.withFallback(datadirConfig)
|
|
||||||
networkConfig.withFallback(conf)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Base directory for all bitcoin-s data. This is the resulting datadir from
|
|
||||||
* the --datadir option and all configuration files.
|
|
||||||
*/
|
|
||||||
lazy val datadir: Path =
|
|
||||||
Paths.get(baseConfig.getString("bitcoin-s.datadir"))
|
|
||||||
|
|
||||||
// start everything!
|
// start everything!
|
||||||
final def run(customFinalDirOpt: Option[String] = None): Unit = {
|
final def run(): Unit = {
|
||||||
|
|
||||||
/** Directory specific for current network or custom dir */
|
|
||||||
val usedDir: Path =
|
|
||||||
DatadirUtil.getFinalDatadir(datadir, baseConfig, customFinalDirOpt)
|
|
||||||
|
|
||||||
//We need to set the system property before any logger instances
|
//We need to set the system property before any logger instances
|
||||||
//are in instantiated. If we don't do this, we will not log to
|
//are in instantiated. If we don't do this, we will not log to
|
||||||
//the correct location
|
//the correct location
|
||||||
//see: https://github.com/bitcoin-s/bitcoin-s/issues/2496
|
//see: https://github.com/bitcoin-s/bitcoin-s/issues/2496
|
||||||
System.setProperty("bitcoins.log.location", usedDir.toAbsolutePath.toString)
|
//System.setProperty("bitcoins.log.location", usedDir.toAbsolutePath.toString)
|
||||||
|
|
||||||
logger.info(s"version=${EnvUtil.getVersion}")
|
logger.info(s"version=${EnvUtil.getVersion}")
|
||||||
|
|
||||||
logger.info(s"using directory ${usedDir.toAbsolutePath.toString}")
|
//logger.info(s"using directory ${usedDir.toAbsolutePath.toString}")
|
||||||
val runner: Future[Unit] = start()
|
val runner: Future[Unit] = start()
|
||||||
runner.failed.foreach { err =>
|
runner.failed.foreach { err =>
|
||||||
logger.error(s"Failed to startup server!", err)
|
logger.error(s"Failed to startup server!", err)
|
||||||
}(scala.concurrent.ExecutionContext.Implicits.global)
|
}(scala.concurrent.ExecutionContext.Implicits.global)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait BitcoinSServerRunner extends BitcoinSRunner {
|
||||||
|
protected def serverArgParser: ServerArgParser
|
||||||
|
}
|
||||||
|
@ -2,8 +2,18 @@ package org.bitcoins.server.util
|
|||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
|
|
||||||
trait BitcoinSApp extends App {
|
trait BitcoinSApp {
|
||||||
def actorSystemName: String
|
def actorSystemName: String
|
||||||
|
|
||||||
implicit lazy val system: ActorSystem = ActorSystem(actorSystemName)
|
implicit lazy val system: ActorSystem = ActorSystem(actorSystemName)
|
||||||
|
|
||||||
|
def commandLineArgs: Array[String]
|
||||||
|
|
||||||
|
/** Useful for projects like the oracle server to specify a custom directory inside of ~./bitcoin-s */
|
||||||
|
def customFinalDirOpt: Option[String]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Trait for using BitcoinS app with a daemon backend */
|
||||||
|
trait BitcoinSAppScalaDaemon extends App with BitcoinSApp {
|
||||||
|
final override def commandLineArgs: Array[String] = args
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
package org.bitcoins.server
|
|
||||||
|
|
||||||
import org.bitcoins.rpc.client.common.BitcoindVersion
|
|
||||||
import org.bitcoins.rpc.util.RpcUtil
|
|
||||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
|
||||||
import org.bitcoins.testkit.fixtures.BitcoinSFixture
|
|
||||||
import org.bitcoins.testkit.util.{AkkaUtil, BitcoinSAsyncTest}
|
|
||||||
import scala.concurrent.duration.DurationInt
|
|
||||||
import java.nio.file.Files
|
|
||||||
import scala.reflect.io.Directory
|
|
||||||
|
|
||||||
class LogLocationTest extends BitcoinSAsyncTest {
|
|
||||||
|
|
||||||
behavior of "LogLocationTest"
|
|
||||||
|
|
||||||
it must "start up and log to the correct location" in {
|
|
||||||
val datadir = BitcoinSTestAppConfig.tmpDir()
|
|
||||||
val directory = new Directory(datadir.toFile)
|
|
||||||
val confFile = datadir.resolve("bitcoin-s.conf")
|
|
||||||
|
|
||||||
for {
|
|
||||||
bitcoind <-
|
|
||||||
BitcoinSFixture.createBitcoindWithFunds(Some(BitcoindVersion.V21))
|
|
||||||
|
|
||||||
// Make it so we connect to the correct bitcoind
|
|
||||||
port = bitcoind.instance.uri.getPort
|
|
||||||
confStr = s"""bitcoin-s.node.peers = ["localhost:$port"]"""
|
|
||||||
_ = Files.write(confFile, confStr.getBytes)
|
|
||||||
|
|
||||||
// Add config options
|
|
||||||
randPort = RpcUtil.randomPort
|
|
||||||
args = Array("--datadir",
|
|
||||||
datadir.toAbsolutePath.toString,
|
|
||||||
"--rpcport",
|
|
||||||
randPort.toString)
|
|
||||||
|
|
||||||
main = new BitcoinSServerMain(args)
|
|
||||||
|
|
||||||
// Start the server in a separate thread
|
|
||||||
runnable = new Runnable {
|
|
||||||
override def run(): Unit = {
|
|
||||||
main.run()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thread = new Thread(runnable)
|
|
||||||
_ = thread.start()
|
|
||||||
// Wait for the server to have successfully started up
|
|
||||||
_ <- AkkaUtil.nonBlockingSleep(1.second)
|
|
||||||
binding <- BitcoinSServer.startedF
|
|
||||||
|
|
||||||
// Stop the server
|
|
||||||
_ <- bitcoind.stop()
|
|
||||||
_ <- binding.terminate(5.seconds)
|
|
||||||
_ = thread.interrupt()
|
|
||||||
_ <- main.stop()
|
|
||||||
} yield {
|
|
||||||
// Cleanup
|
|
||||||
directory.deleteRecursively()
|
|
||||||
|
|
||||||
val expectedDir = datadir.resolve("regtest")
|
|
||||||
|
|
||||||
// Check the log location was correctly set
|
|
||||||
assert(
|
|
||||||
System.getProperty("bitcoins.log.location") == expectedDir.toString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package org.bitcoins.server
|
package org.bitcoins.server
|
||||||
|
|
||||||
|
import org.bitcoins.db.util.ServerArgParser
|
||||||
import org.bitcoins.rpc.util.RpcUtil
|
import org.bitcoins.rpc.util.RpcUtil
|
||||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||||
import org.bitcoins.testkit.util.{AkkaUtil, BitcoinSAsyncTest}
|
import org.bitcoins.testkit.util.{AkkaUtil, BitcoinSAsyncTest}
|
||||||
@ -19,16 +20,18 @@ class ServerRunTest extends BitcoinSAsyncTest {
|
|||||||
// Note: on this test passing it will output a stack trace
|
// Note: on this test passing it will output a stack trace
|
||||||
// because runMain calls err.printStackTrace() on failure
|
// because runMain calls err.printStackTrace() on failure
|
||||||
it must "throw errors" in {
|
it must "throw errors" in {
|
||||||
val datadir = BitcoinSTestAppConfig.tmpDir()
|
implicit val config = BitcoinSTestAppConfig.getNeutrinoTestConfig()
|
||||||
|
val datadir = config.chainConf.datadir
|
||||||
val directory = new Directory(datadir.toFile)
|
val directory = new Directory(datadir.toFile)
|
||||||
|
|
||||||
val randPort = RpcUtil.randomPort
|
val randPort = RpcUtil.randomPort
|
||||||
val args = Array("--datadir",
|
val args = Vector("--datadir",
|
||||||
datadir.toAbsolutePath.toString,
|
datadir.toAbsolutePath.toString,
|
||||||
"--rpcport",
|
"--rpcport",
|
||||||
randPort.toString)
|
randPort.toString)
|
||||||
|
|
||||||
val main = new BitcoinSServerMain(args)
|
val serverArgParser = ServerArgParser(args)
|
||||||
|
val main = new BitcoinSServerMain(serverArgParser)
|
||||||
val runMainF = main.start()
|
val runMainF = main.start()
|
||||||
// Use Exception because different errors can occur
|
// Use Exception because different errors can occur
|
||||||
val assertionF: Future[Assertion] = recoverToSucceededIf[Exception] {
|
val assertionF: Future[Assertion] = recoverToSucceededIf[Exception] {
|
||||||
|
@ -6,6 +6,7 @@ import org.bitcoins.chain.config.ChainAppConfig
|
|||||||
import org.bitcoins.commons.file.FileUtil
|
import org.bitcoins.commons.file.FileUtil
|
||||||
import org.bitcoins.core.util.StartStopAsync
|
import org.bitcoins.core.util.StartStopAsync
|
||||||
import org.bitcoins.db.AppConfig
|
import org.bitcoins.db.AppConfig
|
||||||
|
import org.bitcoins.db.util.ServerArgParser
|
||||||
import org.bitcoins.dlc.wallet.DLCAppConfig
|
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
|
||||||
@ -123,6 +124,18 @@ object BitcoinSAppConfig extends Logging {
|
|||||||
fromConfig(ConfigFactory.load())
|
fromConfig(ConfigFactory.load())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def fromDatadir(datadir: Path, confs: Config*)(implicit
|
||||||
|
ec: ExecutionContext): BitcoinSAppConfig = {
|
||||||
|
BitcoinSAppConfig(datadir, confs: _*)
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromDatadirWithServerArgs(
|
||||||
|
datadir: Path,
|
||||||
|
serverArgsParser: ServerArgParser)(implicit
|
||||||
|
ec: ExecutionContext): BitcoinSAppConfig = {
|
||||||
|
fromDatadir(datadir, serverArgsParser.toConfig)
|
||||||
|
}
|
||||||
|
|
||||||
/** Constructs an app configuration from the default Bitcoin-S
|
/** Constructs an app configuration from the default Bitcoin-S
|
||||||
* data directory and given list of configuration overrides.
|
* data directory and given list of configuration overrides.
|
||||||
*/
|
*/
|
||||||
@ -132,8 +145,15 @@ object BitcoinSAppConfig extends Logging {
|
|||||||
|
|
||||||
def fromDefaultDatadirWithBundleConf(confs: Vector[Config] = Vector.empty)(
|
def fromDefaultDatadirWithBundleConf(confs: Vector[Config] = Vector.empty)(
|
||||||
implicit ec: ExecutionContext): BitcoinSAppConfig = {
|
implicit ec: ExecutionContext): BitcoinSAppConfig = {
|
||||||
|
fromDatadirWithBundleConf(AppConfig.DEFAULT_BITCOIN_S_DATADIR, confs)
|
||||||
|
}
|
||||||
|
|
||||||
|
def fromDatadirWithBundleConf(
|
||||||
|
datadir: Path,
|
||||||
|
confs: Vector[Config] = Vector.empty)(implicit
|
||||||
|
ec: ExecutionContext): BitcoinSAppConfig = {
|
||||||
val baseConf: BitcoinSAppConfig =
|
val baseConf: BitcoinSAppConfig =
|
||||||
BitcoinSAppConfig.fromDefaultDatadir()
|
fromDatadir(datadir, confs: _*)
|
||||||
|
|
||||||
// Grab saved bundle config
|
// Grab saved bundle config
|
||||||
val bundleConfFile =
|
val bundleConfFile =
|
||||||
@ -148,6 +168,27 @@ object BitcoinSAppConfig extends Logging {
|
|||||||
baseConf.copyWithConfig(extraConfig +: confs)
|
baseConf.copyWithConfig(extraConfig +: confs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolve BitcoinSAppConfig in the following order of precedence
|
||||||
|
* 1. Server args
|
||||||
|
* 2. bitcoin-s-bundle.conf
|
||||||
|
* 3. bitcoin-s.conf
|
||||||
|
* 4. application.conf
|
||||||
|
* 5. reference.conf
|
||||||
|
*/
|
||||||
|
def fromDatadirWithBundleConfWithServerArgs(
|
||||||
|
datadir: Path,
|
||||||
|
serverArgParser: ServerArgParser)(implicit
|
||||||
|
ec: ExecutionContext): BitcoinSAppConfig = {
|
||||||
|
fromDatadirWithBundleConf(datadir, Vector(serverArgParser.toConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a BitcoinSAppConfig the the given daemon args to a server */
|
||||||
|
def fromDefaultDatadirWithServerArgs(serverArgParser: ServerArgParser)(
|
||||||
|
implicit ec: ExecutionContext): BitcoinSAppConfig = {
|
||||||
|
val config = serverArgParser.toConfig
|
||||||
|
fromConfig(config)
|
||||||
|
}
|
||||||
|
|
||||||
import scala.language.implicitConversions
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
/** Converts the given implicit config to a wallet config */
|
/** Converts the given implicit config to a wallet config */
|
||||||
|
@ -12,6 +12,7 @@ import org.bitcoins.core.api.feeprovider.FeeRateApi
|
|||||||
import org.bitcoins.core.api.node.NodeApi
|
import org.bitcoins.core.api.node.NodeApi
|
||||||
import org.bitcoins.core.util.NetworkUtil
|
import org.bitcoins.core.util.NetworkUtil
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
|
import org.bitcoins.db.util.{DatadirParser, ServerArgParser}
|
||||||
import org.bitcoins.dlc.wallet._
|
import org.bitcoins.dlc.wallet._
|
||||||
import org.bitcoins.feeprovider.FeeProviderName._
|
import org.bitcoins.feeprovider.FeeProviderName._
|
||||||
import org.bitcoins.feeprovider.MempoolSpaceTarget.HourFeeTarget
|
import org.bitcoins.feeprovider.MempoolSpaceTarget.HourFeeTarget
|
||||||
@ -20,19 +21,17 @@ import org.bitcoins.node._
|
|||||||
import org.bitcoins.node.config.NodeAppConfig
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
import org.bitcoins.node.models.Peer
|
import org.bitcoins.node.models.Peer
|
||||||
import org.bitcoins.rpc.config.ZmqConfig
|
import org.bitcoins.rpc.config.ZmqConfig
|
||||||
import org.bitcoins.server.routes.{BitcoinSRunner, Server}
|
import org.bitcoins.server.routes.{BitcoinSServerRunner, Server}
|
||||||
import org.bitcoins.server.util.BitcoinSApp
|
import org.bitcoins.server.util.BitcoinSAppScalaDaemon
|
||||||
import org.bitcoins.wallet.Wallet
|
import org.bitcoins.wallet.Wallet
|
||||||
import org.bitcoins.wallet.config.WalletAppConfig
|
import org.bitcoins.wallet.config.WalletAppConfig
|
||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future, Promise}
|
import scala.concurrent.{ExecutionContext, Future, Promise}
|
||||||
|
|
||||||
class BitcoinSServerMain(override val args: Array[String])(implicit
|
class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
||||||
override val system: ActorSystem)
|
override val system: ActorSystem,
|
||||||
extends BitcoinSRunner {
|
conf: BitcoinSAppConfig)
|
||||||
|
extends BitcoinSServerRunner {
|
||||||
implicit lazy val conf: BitcoinSAppConfig =
|
|
||||||
BitcoinSAppConfig(datadir, baseConfig)
|
|
||||||
|
|
||||||
implicit lazy val walletConf: WalletAppConfig = conf.walletConf
|
implicit lazy val walletConf: WalletAppConfig = conf.walletConf
|
||||||
implicit lazy val nodeConf: NodeAppConfig = conf.nodeConf
|
implicit lazy val nodeConf: NodeAppConfig = conf.nodeConf
|
||||||
@ -92,7 +91,7 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
|
|||||||
|
|
||||||
//run chain work migration
|
//run chain work migration
|
||||||
val chainApiF = runChainWorkCalc(
|
val chainApiF = runChainWorkCalc(
|
||||||
forceChainWorkRecalc || chainConf.forceRecalcChainWork)
|
serverArgParser.forceChainWorkRecalc || chainConf.forceRecalcChainWork)
|
||||||
|
|
||||||
//get a node that isn't started
|
//get a node that isn't started
|
||||||
val nodeF = nodeConf.createNode(peer)(chainConf, system)
|
val nodeF = nodeConf.createNode(peer)(chainConf, system)
|
||||||
@ -141,8 +140,7 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
|
|||||||
binding <- startHttpServer(nodeApi = node,
|
binding <- startHttpServer(nodeApi = node,
|
||||||
chainApi = chainApi,
|
chainApi = chainApi,
|
||||||
wallet = wallet,
|
wallet = wallet,
|
||||||
rpcbindOpt = rpcBindOpt,
|
serverCmdLineArgs = serverArgParser)
|
||||||
rpcPortOpt = rpcPortOpt)
|
|
||||||
_ = {
|
_ = {
|
||||||
logger.info(
|
logger.info(
|
||||||
s"Starting ${nodeConf.nodeType.shortName} node sync, it took=${System
|
s"Starting ${nodeConf.nodeType.shortName} node sync, it took=${System
|
||||||
@ -206,8 +204,7 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
|
|||||||
binding <- startHttpServer(nodeApi = bitcoind,
|
binding <- startHttpServer(nodeApi = bitcoind,
|
||||||
chainApi = bitcoind,
|
chainApi = bitcoind,
|
||||||
wallet = wallet,
|
wallet = wallet,
|
||||||
rpcbindOpt = rpcBindOpt,
|
serverCmdLineArgs = serverArgParser)
|
||||||
rpcPortOpt = rpcPortOpt)
|
|
||||||
_ = BitcoinSServer.startedFP.success(Future.successful(binding))
|
_ = BitcoinSServer.startedFP.success(Future.successful(binding))
|
||||||
} yield {
|
} yield {
|
||||||
logger.info(s"Done starting Main!")
|
logger.info(s"Done starting Main!")
|
||||||
@ -297,8 +294,7 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
|
|||||||
nodeApi: NodeApi,
|
nodeApi: NodeApi,
|
||||||
chainApi: ChainApi,
|
chainApi: ChainApi,
|
||||||
wallet: DLCWallet,
|
wallet: DLCWallet,
|
||||||
rpcbindOpt: Option[String],
|
serverCmdLineArgs: ServerArgParser)(implicit
|
||||||
rpcPortOpt: Option[Int])(implicit
|
|
||||||
system: ActorSystem,
|
system: ActorSystem,
|
||||||
conf: BitcoinSAppConfig): Future[Http.ServerBinding] = {
|
conf: BitcoinSAppConfig): Future[Http.ServerBinding] = {
|
||||||
implicit val nodeConf: NodeAppConfig = conf.nodeConf
|
implicit val nodeConf: NodeAppConfig = conf.nodeConf
|
||||||
@ -309,13 +305,13 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
|
|||||||
val chainRoutes = ChainRoutes(chainApi, nodeConf.network)
|
val chainRoutes = ChainRoutes(chainApi, nodeConf.network)
|
||||||
val coreRoutes = CoreRoutes(Core)
|
val coreRoutes = CoreRoutes(Core)
|
||||||
|
|
||||||
val bindConfOpt = rpcbindOpt match {
|
val bindConfOpt = serverCmdLineArgs.rpcBindOpt match {
|
||||||
case Some(rpcbind) => Some(rpcbind)
|
case Some(rpcbind) => Some(rpcbind)
|
||||||
case None => conf.rpcBindOpt
|
case None => conf.rpcBindOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
val server = {
|
val server = {
|
||||||
rpcPortOpt match {
|
serverCmdLineArgs.rpcPortOpt match {
|
||||||
case Some(rpcport) =>
|
case Some(rpcport) =>
|
||||||
Server(conf = nodeConf,
|
Server(conf = nodeConf,
|
||||||
handlers =
|
handlers =
|
||||||
@ -392,12 +388,27 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object BitcoinSServerMain extends BitcoinSApp {
|
object BitcoinSServerMain extends BitcoinSAppScalaDaemon {
|
||||||
|
|
||||||
override val actorSystemName =
|
override val actorSystemName =
|
||||||
s"bitcoin-s-server-${System.currentTimeMillis()}"
|
s"bitcoin-s-server-${System.currentTimeMillis()}"
|
||||||
|
|
||||||
new BitcoinSServerMain(args).run()
|
/** Directory specific for current network or custom dir */
|
||||||
|
override val customFinalDirOpt: Option[String] = None
|
||||||
|
|
||||||
|
val serverCmdLineArgs = ServerArgParser(args.toVector)
|
||||||
|
|
||||||
|
val datadirParser =
|
||||||
|
DatadirParser(serverCmdLineArgs, customFinalDirOpt)
|
||||||
|
|
||||||
|
System.setProperty("bitcoins.log.location", datadirParser.networkDir.toString)
|
||||||
|
|
||||||
|
implicit lazy val conf: BitcoinSAppConfig =
|
||||||
|
BitcoinSAppConfig(datadirParser.datadir,
|
||||||
|
datadirParser.baseConfig,
|
||||||
|
serverCmdLineArgs.toConfig)(system.dispatcher)
|
||||||
|
|
||||||
|
new BitcoinSServerMain(serverCmdLineArgs).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
object BitcoinSServer {
|
object BitcoinSServer {
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package org.bitcoins.db.util
|
||||||
|
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||||
|
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||||
|
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
class ServerArgParserTest extends BitcoinSUnitTest {
|
||||||
|
|
||||||
|
behavior of "ServerArgParser"
|
||||||
|
|
||||||
|
it must "handle no command line flags" in {
|
||||||
|
val parser = ServerArgParser(Vector.empty)
|
||||||
|
|
||||||
|
//config must be empty
|
||||||
|
assert(parser.toConfig == ConfigFactory.empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
it must "handle having all command line args we support" in {
|
||||||
|
val datadir = BitcoinSTestAppConfig.tmpDir()
|
||||||
|
val datadirString = datadir.toAbsolutePath.toString
|
||||||
|
val args = Vector("--rpcport",
|
||||||
|
"1234",
|
||||||
|
"--rpcbind",
|
||||||
|
"my.cool.site.com",
|
||||||
|
"--datadir",
|
||||||
|
s"${datadirString}",
|
||||||
|
"--force-recalc-chainwork")
|
||||||
|
val parser = ServerArgParser(args)
|
||||||
|
|
||||||
|
val config = parser.toConfig
|
||||||
|
|
||||||
|
val datadirPathConfigKey = s"bitcoin-s.datadir"
|
||||||
|
|
||||||
|
assert(config.hasPath(datadirPathConfigKey))
|
||||||
|
assert(config.hasPath(s"bitcoin-s.server.rpcbind"))
|
||||||
|
assert(config.hasPath(s"bitcoin-s.server.rpcport"))
|
||||||
|
assert(config.hasPath(s"bitcoin-s.chain.force-recalc-chainwork"))
|
||||||
|
val datadirFromConfig = config.getString(datadirPathConfigKey)
|
||||||
|
val path = Paths.get(datadirFromConfig)
|
||||||
|
assert(path == datadir)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package org.bitcoins.db.util
|
||||||
|
|
||||||
|
import com.typesafe.config.{Config, ConfigFactory}
|
||||||
|
import org.bitcoins.db.AppConfig
|
||||||
|
import org.bitcoins.db.AppConfig.safePathToString
|
||||||
|
|
||||||
|
import java.nio.file.{Path, Paths}
|
||||||
|
|
||||||
|
/** Parses the correct datadir given the possible input sources for datadir config
|
||||||
|
* 1. The --datadir command line flag
|
||||||
|
* 2. Inferring the datadir based on the bitcoin network configured
|
||||||
|
* 3. ??? Anything else i'm forgetting ????
|
||||||
|
*/
|
||||||
|
case class DatadirParser(
|
||||||
|
serverArgs: ServerArgParser,
|
||||||
|
customFinalDirOpt: Option[String]) {
|
||||||
|
|
||||||
|
/** Sets the default data dir, overridden by the --datadir option */
|
||||||
|
private lazy val datadirPath: Path = serverArgs.datadirOpt match {
|
||||||
|
case None => AppConfig.DEFAULT_BITCOIN_S_DATADIR
|
||||||
|
case Some(datadir) => datadir
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val datadirConfig: Config =
|
||||||
|
ConfigFactory.parseString(
|
||||||
|
s"bitcoin-s.datadir = ${safePathToString(datadirPath)}")
|
||||||
|
|
||||||
|
lazy val networkConfig: Config = serverArgs.networkOpt match {
|
||||||
|
case Some(network) =>
|
||||||
|
val networkStr = DatadirUtil.networkStrToDirName(network.name)
|
||||||
|
ConfigFactory.parseString(s"bitcoin-s.network = $networkStr")
|
||||||
|
case None => ConfigFactory.empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val baseConfig: Config = {
|
||||||
|
serverArgs.configOpt match {
|
||||||
|
case None =>
|
||||||
|
AppConfig
|
||||||
|
.getBaseConfig(datadirPath, List(networkConfig))
|
||||||
|
.withFallback(datadirConfig)
|
||||||
|
.resolve()
|
||||||
|
case Some(config) =>
|
||||||
|
val conf = ConfigFactory
|
||||||
|
.parseFile(config.toFile)
|
||||||
|
.withFallback(datadirConfig)
|
||||||
|
networkConfig.withFallback(conf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Base directory for all bitcoin-s data. This is the resulting datadir from
|
||||||
|
* the --datadir option and all configuration files.
|
||||||
|
*/
|
||||||
|
lazy val datadir: Path =
|
||||||
|
Paths.get(baseConfig.getString("bitcoin-s.datadir"))
|
||||||
|
|
||||||
|
/** Directory specific for current network or custom dir
|
||||||
|
* Examples are
|
||||||
|
* HOME/.bitcoin-s/mainnet
|
||||||
|
* HOME/.bitcoin-s/testnet3
|
||||||
|
* HOME/.bitcoin-s/oracle
|
||||||
|
*/
|
||||||
|
def networkDir: Path =
|
||||||
|
DatadirUtil.getFinalDatadir(datadir, baseConfig, customFinalDirOpt)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.bitcoins.server.util
|
package org.bitcoins.db.util
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import org.bitcoins.core.config._
|
import org.bitcoins.core.config._
|
@ -0,0 +1,124 @@
|
|||||||
|
package org.bitcoins.db.util
|
||||||
|
|
||||||
|
import com.typesafe.config.{Config, ConfigFactory}
|
||||||
|
import org.bitcoins.core.config._
|
||||||
|
import org.bitcoins.db.AppConfig
|
||||||
|
|
||||||
|
import java.nio.file.{Path, Paths}
|
||||||
|
import scala.util.Properties
|
||||||
|
|
||||||
|
/** Parses arguments passed to the bitcoin-s app server as command line arguments
|
||||||
|
* This does NOT consider things that exist in reference.conf or application.conf files
|
||||||
|
*/
|
||||||
|
case class ServerArgParser(commandLineArgs: Vector[String]) {
|
||||||
|
|
||||||
|
private lazy val argsWithIndex: Vector[(String, Int)] =
|
||||||
|
commandLineArgs.zipWithIndex
|
||||||
|
|
||||||
|
/** The ip address we are binding the server to */
|
||||||
|
lazy val rpcBindOpt: Option[String] = {
|
||||||
|
val rpcbindOpt = argsWithIndex.find(_._1.toLowerCase == "--rpcbind")
|
||||||
|
rpcbindOpt.map { case (_, idx) =>
|
||||||
|
commandLineArgs(idx + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val rpcPortOpt: Option[Int] = {
|
||||||
|
val portOpt = argsWithIndex.find(_._1.toLowerCase == "--rpcport")
|
||||||
|
portOpt.map { case (_, idx) =>
|
||||||
|
commandLineArgs(idx + 1).toInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val networkOpt: Option[BitcoinNetwork] = {
|
||||||
|
val netOpt = argsWithIndex.find(_._1.toLowerCase == "--network")
|
||||||
|
netOpt.map { case (_, idx) =>
|
||||||
|
val string = commandLineArgs(idx + 1)
|
||||||
|
string.toLowerCase match {
|
||||||
|
case "mainnet" => MainNet
|
||||||
|
case "main" => MainNet
|
||||||
|
case "testnet3" => TestNet3
|
||||||
|
case "testnet" => TestNet3
|
||||||
|
case "test" => TestNet3
|
||||||
|
case "regtest" => RegTest
|
||||||
|
case "signet" => SigNet
|
||||||
|
case "sig" => SigNet
|
||||||
|
case _: String =>
|
||||||
|
throw new IllegalArgumentException(s"Invalid network $string")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy val dataDirIndexOpt: Option[(String, Int)] = {
|
||||||
|
argsWithIndex.find(_._1.toLowerCase == "--datadir")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The datadir passed in as a command line arg using --datadir */
|
||||||
|
lazy val datadirOpt: Option[Path] = dataDirIndexOpt.map { case (_, idx) =>
|
||||||
|
val str = commandLineArgs(idx + 1)
|
||||||
|
//we only want the replace ~ if it is first in the file path
|
||||||
|
//otherwise windows gets mangled as it can have parts of the file path containing ~
|
||||||
|
//https://stackoverflow.com/a/7163455/967713
|
||||||
|
//C:\Users\RUNNER~1\AppData\Local\Temp\bitcoin-s-13391384540028797275
|
||||||
|
val usableStr = str.replaceFirst("^~", Properties.userHome)
|
||||||
|
Paths.get(usableStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy val configIndexOpt: Option[Int] = {
|
||||||
|
argsWithIndex.find(_._1.toLowerCase == "--conf").map(_._2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A custom configuration file passed in as a command line arg with --conf */
|
||||||
|
lazy val configOpt: Option[Path] = {
|
||||||
|
configIndexOpt.map { idx =>
|
||||||
|
val str = commandLineArgs(idx + 1)
|
||||||
|
val usableStr = str.replace("~", Properties.userHome)
|
||||||
|
Paths.get(usableStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val forceChainWorkRecalc: Boolean =
|
||||||
|
commandLineArgs.exists(_.toLowerCase == "--force-recalc-chainwork")
|
||||||
|
|
||||||
|
/** Converts the given command line args into a Config object.
|
||||||
|
* There is one exclusion to this, we cannot write the --conf
|
||||||
|
* flag to the config file as that is self referential
|
||||||
|
*/
|
||||||
|
def toConfig: Config = {
|
||||||
|
val rpcPortString = rpcPortOpt match {
|
||||||
|
case Some(rpcPort) =>
|
||||||
|
s"bitcoin-s.server.rpcport=$rpcPort\n"
|
||||||
|
case None => s""
|
||||||
|
}
|
||||||
|
|
||||||
|
val rpcBindString = rpcBindOpt match {
|
||||||
|
case Some(rpcbind) =>
|
||||||
|
s"bitcoin-s.server.rpcbind=$rpcbind\n"
|
||||||
|
case None => s""
|
||||||
|
}
|
||||||
|
|
||||||
|
val datadirString = datadirOpt match {
|
||||||
|
case Some(datadir) =>
|
||||||
|
s"bitcoin-s.datadir=" + AppConfig.safePathToString(datadir) + "\n"
|
||||||
|
case None => s""
|
||||||
|
}
|
||||||
|
|
||||||
|
val forceChainWorkRecalcString = if (forceChainWorkRecalc) {
|
||||||
|
s"bitcoin-s.chain.force-recalc-chainwork=$forceChainWorkRecalc\n"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
//omitting configOpt as i don't know if we can do anything with that?
|
||||||
|
|
||||||
|
val all =
|
||||||
|
rpcPortString + rpcBindString + datadirString + forceChainWorkRecalcString
|
||||||
|
|
||||||
|
ConfigFactory.parseString(all)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object ServerArgParser {
|
||||||
|
val empty: ServerArgParser = ServerArgParser(Vector.empty)
|
||||||
|
}
|
@ -130,7 +130,7 @@ abstract class Wallet
|
|||||||
if (account.xpub != xpub) {
|
if (account.xpub != xpub) {
|
||||||
val errorMsg =
|
val errorMsg =
|
||||||
s"Divergent xpubs for account=$account. Existing database xpub=${account.xpub}, key manager's xpub=$xpub. " +
|
s"Divergent xpubs for account=$account. Existing database xpub=${account.xpub}, key manager's xpub=$xpub. " +
|
||||||
s"It is possible we have a different key manager being used than expected, key manager=$keyManager"
|
s"It is possible we have a different key manager being used than expected, key manager=${keyManager.kmParams.seedPath.toAbsolutePath.toString}"
|
||||||
Future.failed(new RuntimeException(errorMsg))
|
Future.failed(new RuntimeException(errorMsg))
|
||||||
} else {
|
} else {
|
||||||
Future.unit
|
Future.unit
|
||||||
@ -995,7 +995,7 @@ object Wallet extends WalletLogger {
|
|||||||
if (account.xpub != xpub) {
|
if (account.xpub != xpub) {
|
||||||
val errorMsg =
|
val errorMsg =
|
||||||
s"Divergent xpubs for account=${account}. Existing database xpub=${account.xpub}, new xpub=${xpub}. " +
|
s"Divergent xpubs for account=${account}. Existing database xpub=${account.xpub}, new xpub=${xpub}. " +
|
||||||
s"It is possible we have a different key manager being used than expected, keymanager=${keyManager}"
|
s"It is possible we have a different key manager being used than expected, keymanager=${keyManager.kmParams.seedPath.toAbsolutePath.toString}"
|
||||||
Future.failed(new RuntimeException(errorMsg))
|
Future.failed(new RuntimeException(errorMsg))
|
||||||
} else {
|
} else {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
|
Loading…
Reference in New Issue
Block a user