Resolve bundle config and read/write in tmp file (#3327)

* Have it save config for next time

* Fix compile
This commit is contained in:
benthecarman 2021-06-28 07:46:32 -05:00 committed by GitHub
parent cb5ec20eac
commit d669bd58ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 38 deletions

View File

@ -1,6 +1,7 @@
package org.bitcoins.bundle.gui
import akka.actor.ActorSystem
import grizzled.slf4j.Logging
import org.bitcoins.gui._
import org.bitcoins.node.NodeType
import org.bitcoins.server.BitcoinSAppConfig
@ -10,13 +11,15 @@ import scalafx.scene.control._
import scalafx.scene.layout._
import scalafx.scene.text._
import scala.concurrent.ExecutionContext.global
import scala.util.Try
class LandingPane(glassPane: VBox)(implicit system: ActorSystem) {
class LandingPane(glassPane: VBox)(implicit system: ActorSystem)
extends Logging {
import system.dispatcher
val appConfig: BitcoinSAppConfig =
BitcoinSAppConfig.fromDefaultDatadir()(global)
BitcoinSAppConfig.fromDefaultDatadirWithBundleConf()
val model = new LandingPaneModel()

View File

@ -4,18 +4,19 @@ import akka.actor.ActorSystem
import com.typesafe.config._
import grizzled.slf4j.Logging
import org.bitcoins.bundle.gui.BundleGUI._
import org.bitcoins.db.AppConfig
import org.bitcoins.gui._
import org.bitcoins.node.NodeType._
import org.bitcoins.node._
import org.bitcoins.server.BitcoinSAppConfig.toNodeConf
import org.bitcoins.server._
import org.bitcoins.server.util.DatadirUtil
import scalafx.beans.property.ObjectProperty
import scalafx.stage.Window
import java.nio.file.Files
import scala.concurrent.duration.DurationInt
import java.nio.file.{Files, Path}
import scala.concurrent._
import scala.jdk.CollectionConverters._
import scala.concurrent.duration.DurationInt
class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
@ -27,38 +28,46 @@ class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
ObjectProperty[Window](null.asInstanceOf[Window])
}
def launchWallet(config: Config, appConfig: BitcoinSAppConfig): Unit = {
def launchWallet(bundleConf: Config, appConfig: BitcoinSAppConfig): Unit = {
taskRunner.run(
"Launching Wallet",
op = {
import system.dispatcher
val file = appConfig.baseDatadir.resolve("bitcoin-s-bundle.conf")
// if the user made changes in the gui, write to file
// We compare sets so we account for resolving the config
val confStr = config
.entrySet()
.asScala
.toVector
.sortBy(_.getKey)
.map { entry => s"${entry.getKey} = ${entry.getValue.render()}" }
.mkString("\n")
val bundleConfStr = AppConfig.configToString(bundleConf)
Files.write(file, confStr.getBytes)
logger.info(s"Writing bundle config to $file")
Files.write(file, bundleConfStr.getBytes)
val extraArgsF: Future[Vector[String]] = {
val usedConf = appConfig.copyWithConfig(Vector(config))
usedConf.nodeType match {
val tmpFile = Files.createTempFile("bitcoin-s-tmp-config", ".conf")
val finalConfF: Future[Path] = {
val tmpConf =
BitcoinSAppConfig.fromConfig(
bundleConf.withFallback(appConfig.config))
val netConfF = tmpConf.nodeType match {
case _: InternalImplementationNodeType =>
// If we are connecting to a node we cannot
// know what network it is on now
Future.successful(Vector.empty)
Future.successful(ConfigFactory.empty())
case BitcoindBackend =>
usedConf.bitcoindRpcConf.client.getBlockChainInfo.map { info =>
val network = info.chain
Vector("--network", network.name)
tmpConf.bitcoindRpcConf.client.getBlockChainInfo.map { info =>
val networkStr =
DatadirUtil.networkStrToDirName(info.chain.name)
ConfigFactory.parseString(s"bitcoin-s.network = $networkStr")
}
}
netConfF.map { netConf =>
val finalConf =
BitcoinSAppConfig.fromDefaultDatadirWithBundleConf(
Vector(netConf, bundleConf))
val totalConfStr = AppConfig.configToString(finalConf.config)
logger.info(s"Writing resolved config to $tmpFile")
Files.write(tmpFile, totalConfStr.getBytes)
}
}
// Launch wallet
@ -69,7 +78,8 @@ class LandingPaneModel()(implicit system: ActorSystem) extends Logging {
promise.success(())
}
extraArgsF.map { extraArgs =>
finalConfF.map { path =>
val extraArgs = Vector("--conf", path.toAbsolutePath.toString)
val usedArgs = extraArgs ++ args
// use class base constructor to share the actor system
new BitcoinSServerMain(usedArgs.toArray).run()

View File

@ -98,10 +98,10 @@ trait BitcoinSRunner extends StartStopAsync[Unit] with Logging {
val str = args(configIndex + 1)
val usableStr = str.replace("~", Properties.userHome)
val path = Paths.get(usableStr)
ConfigFactory
val conf = ConfigFactory
.parseFile(path.toFile)
.withFallback(datadirConfig)
.resolveWith(networkConfig)
networkConfig.withFallback(conf)
}
/** Base directory for all bitcoin-s data. This is the resulting datadir from

View File

@ -1,6 +1,7 @@
package org.bitcoins.server
import com.typesafe.config.{Config, ConfigFactory}
import grizzled.slf4j.Logging
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.commons.file.FileUtil
import org.bitcoins.core.util.StartStopAsync
@ -10,7 +11,7 @@ import org.bitcoins.keymanager.config.KeyManagerAppConfig
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.wallet.config.WalletAppConfig
import java.nio.file.{Path, Paths}
import java.nio.file.{Files, Path, Paths}
import scala.concurrent.{ExecutionContext, Future}
/** A unified config class for all submodules of Bitcoin-S
@ -109,7 +110,7 @@ case class BitcoinSAppConfig(
/** Implicit conversions that allow a unified configuration
* to be passed in wherever a specializes one is required
*/
object BitcoinSAppConfig {
object BitcoinSAppConfig extends Logging {
def fromConfig(config: Config)(implicit
ec: ExecutionContext): BitcoinSAppConfig = {
@ -129,6 +130,24 @@ object BitcoinSAppConfig {
ec: ExecutionContext): BitcoinSAppConfig =
BitcoinSAppConfig(AppConfig.DEFAULT_BITCOIN_S_DATADIR, confs: _*)
def fromDefaultDatadirWithBundleConf(confs: Vector[Config] = Vector.empty)(
implicit ec: ExecutionContext): BitcoinSAppConfig = {
val baseConf: BitcoinSAppConfig =
BitcoinSAppConfig.fromDefaultDatadir()
// Grab saved bundle config
val bundleConfFile =
toChainConf(baseConf).baseDatadir.resolve("bitcoin-s-bundle.conf")
val extraConfig = if (Files.isReadable(bundleConfFile)) {
ConfigFactory.parseFile(bundleConfFile.toFile)
} else {
logger.debug("No saved bundle config found")
ConfigFactory.empty()
}
baseConf.copyWithConfig(extraConfig +: confs)
}
import scala.language.implicitConversions
/** Converts the given implicit config to a wallet config */

View File

@ -43,6 +43,8 @@ class BitcoinSServerMain(override val args: Array[String])(implicit
override def start(): Future[Unit] = {
val startedConfigF = conf.start()
logger.info(s"Start on network ${walletConf.network}")
startedConfigF.failed.foreach { err =>
logger.error(s"Failed to initialize configuration for BitcoinServerMain",
err)

View File

@ -2,11 +2,12 @@ package org.bitcoins.db
import com.typesafe.config._
import grizzled.slf4j.Logging
import org.bitcoins.core.compat.JavaConverters._
import org.bitcoins.core.config._
import org.bitcoins.core.protocol.blockchain.BitcoinChainParams
import org.bitcoins.core.util.StartStopAsync
import java.nio.file.{Files, Path, Paths}
import java.nio.file._
import scala.concurrent.Future
import scala.util.Properties
import scala.util.matching.Regex
@ -165,6 +166,15 @@ object AppConfig extends Logging {
s""""$pathStr"""" // Add quotes around it
}
def configToString(config: Config): String = {
config
.entrySet()
.asScala
.toVector
.map { entry => s"${entry.getKey} = ${entry.getValue.render()}" }
.mkString("\n")
}
def getBaseConfig(
baseDatadir: Path,
configOverrides: List[Config] = List.empty): Config = {
@ -180,17 +190,10 @@ object AppConfig extends Logging {
ConfigFactory.empty()
}
val extraFile = baseDatadir.resolve("bitcoin-s-bundle.conf")
val extraConfig = if (Files.isReadable(extraFile)) {
ConfigFactory.parseFile(extraFile.toFile, configOptions)
} else {
ConfigFactory.empty()
}
val withDatadir =
ConfigFactory.parseString(
s"bitcoin-s.datadir = ${safePathToString(baseDatadir)}")
withDatadir.withFallback(extraConfig.withFallback(config))
withDatadir.withFallback(config)
}
// we want to NOT resolve substitutions in the configuration until the user