diff --git a/app/server/src/main/resources/logback.xml b/app/server/src/main/resources/logback.xml
index 5d9e0431c0..55c5b41108 100644
--- a/app/server/src/main/resources/logback.xml
+++ b/app/server/src/main/resources/logback.xml
@@ -10,4 +10,28 @@
+
+
+
+ %date{yyyy-MM-dd'T'HH:mm:ss,SSXXX} %level [%logger{0}] %msg%n
+
+
+
+
+ 8192
+ true
+
+
+
+
+ ${bitcoins.log.location}
+
+ %date{yyyy-MM-dd'T'HH:mm:ss,SSXXX} %level [%logger{0}] %msg%n
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/server/src/main/resources/reference.conf b/app/server/src/main/resources/reference.conf
index 638688e3e7..888ec6e5c8 100644
--- a/app/server/src/main/resources/reference.conf
+++ b/app/server/src/main/resources/reference.conf
@@ -90,8 +90,27 @@ bitcoin-s {
akka {
- loglevel = "INFO"
- stdout-loglevel = "OFF"
+ # Loggers to register at boot time (akka.event.Logging$DefaultLogger logs
+ # to STDOUT)
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+
+ # Log level used by the configured loggers (see "loggers") as soon
+ # as they have been started; before that, see "stdout-loglevel"
+ # Options: OFF, ERROR, WARNING, INFO, DEBUG
+ loglevel = "DEBUG"
+
+ # Log level for the very basic logger activated during ActorSystem startup.
+ # This logger prints the log messages to stdout (System.out).
+ # Options: OFF, ERROR, WARNING, INFO, DEBUG
+ stdout-loglevel = "DEBUG"
+
+ # Filter of log events that is used by the LoggingAdapter before
+ # publishing log events to the eventStream.
+ logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
+
+ use-slf4j = on
+
+ log-config-on-start = off
actor {
debug {
diff --git a/app/server/src/main/scala/org/bitcoins/server/Main.scala b/app/server/src/main/scala/org/bitcoins/server/Main.scala
index f64095ef28..d1bf5c37b9 100644
--- a/app/server/src/main/scala/org/bitcoins/server/Main.scala
+++ b/app/server/src/main/scala/org/bitcoins/server/Main.scala
@@ -1,6 +1,6 @@
package org.bitcoins.server
-import java.nio.file.Paths
+import java.nio.file.{Path, Paths}
import akka.actor.ActorSystem
import akka.dispatch.Dispatchers
@@ -14,6 +14,7 @@ import org.bitcoins.chain.models.{
CompactFilterHeaderDAO
}
import org.bitcoins.core.Core
+import org.bitcoins.core.config.{BitcoinNetworks, MainNet, RegTest, TestNet3}
import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil, NetworkUtil}
import org.bitcoins.db.AppConfig
import org.bitcoins.feeprovider.BitcoinerLiveFeeRateProvider
@@ -28,21 +29,41 @@ import scala.concurrent.{ExecutionContext, Future, Promise}
object Main extends App with BitcoinSLogger {
private def runMain(): Unit = {
- implicit val system: ActorSystem = ActorSystem("bitcoin-s")
- implicit val ec: ExecutionContext = system.dispatcher
val argsWithIndex = args.zipWithIndex
- implicit val conf: BitcoinSAppConfig = {
+ val dataDirIndexOpt = {
+ argsWithIndex.find(_._1.toLowerCase == "--datadir")
+ }
+ val datadirPath = dataDirIndexOpt match {
+ case None => AppConfig.DEFAULT_BITCOIN_S_DATADIR
+ case Some((_, dataDirIndex)) =>
+ val str = args(dataDirIndex + 1)
+ Paths.get(str)
+ }
- val dataDirIndexOpt = {
- argsWithIndex.find(_._1.toLowerCase == "--datadir")
- }
- val datadirPath = dataDirIndexOpt match {
- case None => AppConfig.DEFAULT_BITCOIN_S_DATADIR
- case Some((_, dataDirIndex)) =>
- val str = args(dataDirIndex + 1)
- Paths.get(str)
+ val baseConfig = AppConfig.getBaseConfig(datadirPath)
+
+ val networkStr = baseConfig.getString("bitcoin-s.network")
+ val network = BitcoinNetworks.fromString(networkStr)
+
+ val datadir: Path = {
+ val lastDirname = network match {
+ case MainNet => "mainnet"
+ case TestNet3 => "testnet3"
+ case RegTest => "regtest"
}
+ datadirPath.resolve(lastDirname)
+ }
+
+ System.setProperty("bitcoins.log.location",
+ datadir.resolve("bitcoin-s.log").toAbsolutePath.toString)
+
+ implicit val system: ActorSystem = ActorSystem("bitcoin-s", baseConfig)
+ implicit val ec: ExecutionContext = system.dispatcher
+
+ system.log.info("Akka logger started")
+
+ implicit val conf: BitcoinSAppConfig = {
BitcoinSAppConfig(datadirPath)
}
diff --git a/db-commons/src/main/scala/org/bitcoins/db/AppConfig.scala b/db-commons/src/main/scala/org/bitcoins/db/AppConfig.scala
index e56a950896..108b9f1365 100644
--- a/db-commons/src/main/scala/org/bitcoins/db/AppConfig.scala
+++ b/db-commons/src/main/scala/org/bitcoins/db/AppConfig.scala
@@ -135,90 +135,17 @@ abstract class AppConfig extends LoggerConfig with StartStopAsync[Unit] {
* The underlying config that we derive the
* rest of the fields in this class from
*/
+ private[bitcoins] lazy val baseConfig: Config = {
+ AppConfig.getBaseConfig(baseDatadir, configOverrides)
+ }
+
private[bitcoins] lazy val config: Config = {
-
- val datadirConfig = {
- val file = baseDatadir.resolve("bitcoin-s.conf")
- val config = if (Files.isReadable(file)) {
- ConfigFactory.parseFile(file.toFile())
- } else {
- ConfigFactory.empty()
- }
-
- val withDatadir =
- ConfigFactory.parseString(s"bitcoin-s.datadir = $baseDatadir")
- withDatadir.withFallback(config)
- }
-
- logger.trace(s"Data directory config:")
- if (datadirConfig.hasPath("bitcoin-s")) {
- logger.trace(datadirConfig.getConfig("bitcoin-s").asReadableJson)
- } else {
- logger.trace(ConfigFactory.empty().asReadableJson)
- }
-
- // `load` tries to resolve substitions,
- // `parseResources` does not
- val dbConfig = ConfigFactory
- .parseResources("db.conf")
-
- logger.trace(
- s"DB config: ${dbConfig.getConfig("bitcoin-s").asReadableJson}")
-
- // we want to NOT resolve substitutions in the configuraton until the user
- // provided configs also has been loaded. .parseResources() does not do that
- // whereas .load() does
- val classPathConfig = {
- val applicationConf = ConfigFactory.parseResources("application.conf")
- val referenceConf = ConfigFactory.parseResources("reference.conf")
- applicationConf.withFallback(referenceConf)
- }
-
- logger.trace(
- s"Classpath config: ${classPathConfig.getConfig("bitcoin-s").asReadableJson}")
-
- // we want the data directory configuration
- // to take preference over any bundled (classpath)
- // configurations
- // loads reference.conf (provided by Bitcoin-S)
- val unresolvedConfig = datadirConfig
- .withFallback(classPathConfig)
- .withFallback(dbConfig)
-
- logger.trace(s"Unresolved bitcoin-s config:")
- logger.trace(unresolvedConfig.getConfig("bitcoin-s").asReadableJson)
-
- val withOverrides =
- if (configOverrides.nonEmpty) {
- val overrides =
- configOverrides
- // we reverse to make the configs specified last take precedent
- .reverse
- .reduce(_.withFallback(_))
-
- val interestingOverrides = overrides.getConfig("bitcoin-s")
- logger.trace(
- s"${configOverrides.length} user-overrides for bitcoin-s config:")
- logger.trace(interestingOverrides.asReadableJson)
-
- // to make the overrides actually override
- // the default setings we have to do it
- // in this order
- overrides.withFallback(unresolvedConfig)
- } else {
- logger.trace(s"No user-provided overrides")
- unresolvedConfig
- }
-
- val finalConfig = withOverrides
- .resolve()
- .getConfig("bitcoin-s")
+ val finalConfig = baseConfig.getConfig("bitcoin-s")
logger.debug(s"Resolved bitcoin-s config:")
logger.debug(finalConfig.asReadableJson)
finalConfig
-
}
/** The base data directory. This is where we look for a configuration file */
@@ -234,7 +161,12 @@ abstract class AppConfig extends LoggerConfig with StartStopAsync[Unit] {
baseDatadir.resolve(lastDirname)
}
- override val logFile: Path = datadir.resolve("bitcoin-s.log")
+ override val logFile: Path = {
+ val path = datadir.resolve("bitcoin-s.log")
+ // Set property for loggers
+ System.setProperty("bitcoins.log.location", path.toAbsolutePath.toString)
+ path
+ }
private def stringToLogLevel(str: String): Option[Level] =
str.toLowerCase() match {
@@ -315,6 +247,64 @@ abstract class AppConfig extends LoggerConfig with StartStopAsync[Unit] {
object AppConfig extends BitcoinSLogger {
+ def getBaseConfig(
+ baseDatadir: Path,
+ configOverrides: List[Config] = List.empty): Config = {
+ val datadirConfig = {
+ val file = baseDatadir.resolve("bitcoin-s.conf")
+ val config = if (Files.isReadable(file)) {
+ ConfigFactory.parseFile(file.toFile)
+ } else {
+ ConfigFactory.empty()
+ }
+
+ val withDatadir =
+ ConfigFactory.parseString(s"bitcoin-s.datadir = $baseDatadir")
+ withDatadir.withFallback(config)
+ }
+
+ // `load` tries to resolve substitions,
+ // `parseResources` does not
+ val dbConfig = ConfigFactory
+ .parseResources("db.conf")
+
+ // we want to NOT resolve substitutions in the configuraton until the user
+ // provided configs also has been loaded. .parseResources() does not do that
+ // whereas .load() does
+ val classPathConfig = {
+ val applicationConf = ConfigFactory.parseResources("application.conf")
+ val referenceConf = ConfigFactory.parseResources("reference.conf")
+ applicationConf.withFallback(referenceConf)
+ }
+
+ // we want the data directory configuration
+ // to take preference over any bundled (classpath)
+ // configurations
+ // loads reference.conf (provided by Bitcoin-S)
+ val unresolvedConfig = datadirConfig
+ .withFallback(classPathConfig)
+ .withFallback(dbConfig)
+
+ val withOverrides =
+ if (configOverrides.nonEmpty) {
+ val overrides =
+ configOverrides
+ // we reverse to make the configs specified last take precedent
+ .reverse
+ .reduce(_.withFallback(_))
+
+ // to make the overrides actually override
+ // the default setings we have to do it
+ // in this order
+ overrides.withFallback(unresolvedConfig)
+ } else {
+ unresolvedConfig
+ }
+
+ withOverrides
+ .resolve()
+ }
+
/** The default data directory
*
* TODO: use different directories on Windows and Mac,
diff --git a/project/Deps.scala b/project/Deps.scala
index 3cc6dd2607..7d2b659732 100644
--- a/project/Deps.scala
+++ b/project/Deps.scala
@@ -8,7 +8,8 @@ object Deps {
val scalacheck = "1.14.3"
val scalaTest = "3.2.0"
- val scalaTestPlus = "3.2.1.0" //super annoying... https://oss.sonatype.org/content/groups/public/org/scalatestplus/
+ val scalaTestPlus =
+ "3.2.1.0" //super annoying... https://oss.sonatype.org/content/groups/public/org/scalatestplus/
val slf4j = "1.7.30"
val spray = "1.3.5"
val zeromq = "0.5.2"
@@ -56,29 +57,62 @@ object Deps {
object Compile {
- val bouncycastle = "org.bouncycastle" % "bcprov-jdk15on" % V.bouncyCastle withSources () withJavadoc ()
- val scodec = "org.scodec" %% "scodec-bits" % V.scodecV withSources () withJavadoc ()
- val slf4j = "org.slf4j" % "slf4j-api" % V.slf4j % "provided" withSources () withJavadoc ()
- val zeromq = "org.zeromq" % "jeromq" % V.zeromq withSources () withJavadoc ()
- val akkaHttp = "com.typesafe.akka" %% "akka-http" % V.akkav withSources () withJavadoc ()
- val akkaStream = "com.typesafe.akka" %% "akka-stream" % V.akkaStreamv withSources () withJavadoc ()
- val akkaActor = "com.typesafe.akka" %% "akka-actor" % V.akkaStreamv withSources () withJavadoc ()
+ val bouncycastle =
+ "org.bouncycastle" % "bcprov-jdk15on" % V.bouncyCastle withSources () withJavadoc ()
+
+ val scodec =
+ "org.scodec" %% "scodec-bits" % V.scodecV withSources () withJavadoc ()
+
+ val slf4j =
+ "org.slf4j" % "slf4j-api" % V.slf4j % "provided" withSources () withJavadoc ()
+
+ val zeromq =
+ "org.zeromq" % "jeromq" % V.zeromq withSources () withJavadoc ()
+
+ val akkaHttp =
+ "com.typesafe.akka" %% "akka-http" % V.akkav withSources () withJavadoc ()
+
+ val akkaStream =
+ "com.typesafe.akka" %% "akka-stream" % V.akkaStreamv withSources () withJavadoc ()
+
+ val akkaActor =
+ "com.typesafe.akka" %% "akka-actor" % V.akkaStreamv withSources () withJavadoc ()
+
+ val akkaSlf4j =
+ "com.typesafe.akka" %% "akka-slf4j" % V.akkaStreamv withSources () withJavadoc ()
+
+ val scalaFx =
+ "org.scalafx" %% "scalafx" % V.scalaFxV withSources () withJavadoc ()
- val scalaFx = "org.scalafx" %% "scalafx" % V.scalaFxV withSources () withJavadoc ()
lazy val osName = System.getProperty("os.name") match {
case n if n.startsWith("Linux") => "linux"
case n if n.startsWith("Mac") => "mac"
case n if n.startsWith("Windows") => "win"
case _ => throw new Exception("Unknown platform!")
}
+
// Not sure if all of these are needed, some might be possible to remove
- lazy val javaFxBase = "org.openjfx" % s"javafx-base" % V.javaFxV classifier osName withSources () withJavadoc ()
- lazy val javaFxControls = "org.openjfx" % s"javafx-controls" % V.javaFxV classifier osName withSources () withJavadoc ()
- lazy val javaFxFxml = "org.openjfx" % s"javafx-fxml" % V.javaFxV classifier osName withSources () withJavadoc ()
- lazy val javaFxGraphics = "org.openjfx" % s"javafx-graphics" % V.javaFxV classifier osName withSources () withJavadoc ()
- lazy val javaFxMedia = "org.openjfx" % s"javafx-media" % V.javaFxV classifier osName withSources () withJavadoc ()
- lazy val javaFxSwing = "org.openjfx" % s"javafx-swing" % V.javaFxV classifier osName withSources () withJavadoc ()
- lazy val javaFxWeb = "org.openjfx" % s"javafx-web" % V.javaFxV classifier osName withSources () withJavadoc ()
+ lazy val javaFxBase =
+ "org.openjfx" % s"javafx-base" % V.javaFxV classifier osName withSources () withJavadoc ()
+
+ lazy val javaFxControls =
+ "org.openjfx" % s"javafx-controls" % V.javaFxV classifier osName withSources () withJavadoc ()
+
+ lazy val javaFxFxml =
+ "org.openjfx" % s"javafx-fxml" % V.javaFxV classifier osName withSources () withJavadoc ()
+
+ lazy val javaFxGraphics =
+ "org.openjfx" % s"javafx-graphics" % V.javaFxV classifier osName withSources () withJavadoc ()
+
+ lazy val javaFxMedia =
+ "org.openjfx" % s"javafx-media" % V.javaFxV classifier osName withSources () withJavadoc ()
+
+ lazy val javaFxSwing =
+ "org.openjfx" % s"javafx-swing" % V.javaFxV classifier osName withSources () withJavadoc ()
+
+ lazy val javaFxWeb =
+ "org.openjfx" % s"javafx-web" % V.javaFxV classifier osName withSources () withJavadoc ()
+
lazy val javaFxDeps = List(javaFxBase,
javaFxControls,
javaFxFxml,
@@ -87,16 +121,23 @@ object Deps {
javaFxSwing,
javaFxWeb)
- val playJson = "com.typesafe.play" %% "play-json" % V.playv withSources () withJavadoc ()
- val typesafeConfig = "com.typesafe" % "config" % V.typesafeConfigV withSources () withJavadoc ()
+ val playJson =
+ "com.typesafe.play" %% "play-json" % V.playv withSources () withJavadoc ()
- val logback = "ch.qos.logback" % "logback-classic" % V.logback withSources () withJavadoc ()
+ val typesafeConfig =
+ "com.typesafe" % "config" % V.typesafeConfigV withSources () withJavadoc ()
+
+ val logback =
+ "ch.qos.logback" % "logback-classic" % V.logback withSources () withJavadoc ()
val codehaus = "org.codehaus.janino" % "janino" % V.codehausV
+
//for loading secp256k1 natively
- val nativeLoader = "org.scijava" % "native-lib-loader" % V.nativeLoaderV withSources () withJavadoc ()
+ val nativeLoader =
+ "org.scijava" % "native-lib-loader" % V.nativeLoaderV withSources () withJavadoc ()
//node deps
- val slick = "com.typesafe.slick" %% "slick" % V.slickV withSources () withJavadoc ()
+ val slick =
+ "com.typesafe.slick" %% "slick" % V.slickV withSources () withJavadoc ()
val slickHikari = "com.typesafe.slick" %% "slick-hikaricp" % V.slickV
val sqlite = "org.xerial" % "sqlite-jdbc" % V.sqliteV
val postgres = "org.postgresql" % "postgresql" % V.postgresV
@@ -115,26 +156,49 @@ object Deps {
// HTTP client lib
val sttp = "com.softwaremill.sttp" %% "core" % V.sttpV
- val scalacheck = "org.scalacheck" %% "scalacheck" % V.scalacheck withSources () withJavadoc ()
- val scalaTest = "org.scalatest" %% "scalatest" % V.scalaTest withSources () withJavadoc ()
- val scalaTestPlus = "org.scalatestplus" %% "scalacheck-1-14" % V.scalaTestPlus withSources () withJavadoc ()
- val pgEmbedded = "com.opentable.components" % "otj-pg-embedded" % V.pgEmbeddedV withSources () withJavadoc ()
+ val scalacheck =
+ "org.scalacheck" %% "scalacheck" % V.scalacheck withSources () withJavadoc ()
+
+ val scalaTest =
+ "org.scalatest" %% "scalatest" % V.scalaTest withSources () withJavadoc ()
+
+ val scalaTestPlus =
+ "org.scalatestplus" %% "scalacheck-1-14" % V.scalaTestPlus withSources () withJavadoc ()
+
+ val pgEmbedded =
+ "com.opentable.components" % "otj-pg-embedded" % V.pgEmbeddedV withSources () withJavadoc ()
}
object Test {
- val newAsync = "org.scala-lang.modules" %% "scala-async" % V.asyncNewScalaV % "test" withSources () withJavadoc ()
- val junitInterface = "com.novocode" % "junit-interface" % V.junitV % "test" withSources () withJavadoc ()
+
+ val newAsync =
+ "org.scala-lang.modules" %% "scala-async" % V.asyncNewScalaV % "test" withSources () withJavadoc ()
+
+ val junitInterface =
+ "com.novocode" % "junit-interface" % V.junitV % "test" withSources () withJavadoc ()
val logback = Compile.logback % "test"
val scalacheck = Compile.scalacheck % "test"
val scalaTest = Compile.scalaTest % "test"
val scalaMock = "org.scalamock" %% "scalamock" % V.scalamockV
- val spray = "io.spray" %% "spray-json" % V.spray % "test" withSources () withJavadoc ()
- val akkaHttp = "com.typesafe.akka" %% "akka-http-testkit" % V.akkav % "test" withSources () withJavadoc ()
- val akkaStream = "com.typesafe.akka" %% "akka-stream-testkit" % V.akkaStreamv % "test" withSources () withJavadoc ()
+
+ val spray =
+ "io.spray" %% "spray-json" % V.spray % "test" withSources () withJavadoc ()
+
+ val akkaHttp =
+ "com.typesafe.akka" %% "akka-http-testkit" % V.akkav % "test" withSources () withJavadoc ()
+
+ val akkaStream =
+ "com.typesafe.akka" %% "akka-stream-testkit" % V.akkaStreamv % "test" withSources () withJavadoc ()
val playJson = Compile.playJson % "test"
- val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % V.akkaActorV withSources () withJavadoc ()
- val scalameter = "com.storm-enroute" %% "scalameter" % V.scalameterV % "test" withSources () withJavadoc ()
- val pgEmbedded = "com.opentable.components" % "otj-pg-embedded" % V.pgEmbeddedV % "test" withSources () withJavadoc ()
+
+ val akkaTestkit =
+ "com.typesafe.akka" %% "akka-testkit" % V.akkaActorV withSources () withJavadoc ()
+
+ val scalameter =
+ "com.storm-enroute" %% "scalameter" % V.scalameterV % "test" withSources () withJavadoc ()
+
+ val pgEmbedded =
+ "com.opentable.components" % "otj-pg-embedded" % V.pgEmbeddedV % "test" withSources () withJavadoc ()
}
val chain = List(
@@ -145,11 +209,12 @@ object Deps {
Test.pgEmbedded
)
- def appCommons(scalaVersion: String) = List(
- Compile.newMicroPickle,
- Compile.playJson,
- Compile.slf4j
- )
+ def appCommons(scalaVersion: String) =
+ List(
+ Compile.newMicroPickle,
+ Compile.playJson,
+ Compile.slf4j
+ )
val core = List(
Compile.bouncycastle,
@@ -193,14 +258,15 @@ object Deps {
Compile.typesafeConfig
)
- def bitcoindRpcTest(scalaVersion: String) = List(
- Test.akkaHttp,
- Test.akkaStream,
- Test.logback,
- Test.scalaTest,
- Test.scalacheck,
- Test.newAsync
- )
+ def bitcoindRpcTest(scalaVersion: String) =
+ List(
+ Test.akkaHttp,
+ Test.akkaStream,
+ Test.logback,
+ Test.scalaTest,
+ Test.scalacheck,
+ Test.newAsync
+ )
val bench = List(
"org.slf4j" % "slf4j-api" % V.slf4j withSources () withJavadoc (),
@@ -219,25 +285,28 @@ object Deps {
Test.pgEmbedded
)
- def cli(scalaVersion: String) = List(
- Compile.sttp,
- Compile.newMicroPickle,
- Compile.logback,
- Compile.scopt,
- //we can remove this dependency when this is fixed
- //https://github.com/oracle/graal/issues/1943
- //see https://github.com/bitcoin-s/bitcoin-s/issues/1100
- Compile.codehaus
- )
+ def cli(scalaVersion: String) =
+ List(
+ Compile.sttp,
+ Compile.newMicroPickle,
+ Compile.logback,
+ Compile.scopt,
+ //we can remove this dependency when this is fixed
+ //https://github.com/oracle/graal/issues/1943
+ //see https://github.com/bitcoin-s/bitcoin-s/issues/1100
+ Compile.codehaus
+ )
val gui = List(Compile.scalaFx) ++ Compile.javaFxDeps
- def server(scalaVersion: String) = List(
- Compile.newMicroPickle,
- Compile.logback,
- Compile.akkaActor,
- Compile.akkaHttp
- )
+ def server(scalaVersion: String) =
+ List(
+ Compile.newMicroPickle,
+ Compile.logback,
+ Compile.akkaActor,
+ Compile.akkaHttp,
+ Compile.akkaSlf4j
+ )
val eclairRpc = List(
Compile.akkaHttp,
@@ -288,19 +357,21 @@ object Deps {
Test.akkaTestkit
)
- def keyManager(scalaVersion: String) = List(
- Compile.newMicroJson
- )
+ def keyManager(scalaVersion: String) =
+ List(
+ Compile.newMicroJson
+ )
val keyManagerTest = List(
Compile.slf4j,
Test.logback
)
- def wallet(scalaVersion: String) = List(
- Compile.newMicroJson,
- Compile.logback
- )
+ def wallet(scalaVersion: String) =
+ List(
+ Compile.newMicroJson,
+ Compile.logback
+ )
val walletTest = List(
Test.akkaTestkit,