mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-19 05:43:51 +01:00
2020 06 12 mv to appconfig (#1553)
* Move hasWallet() to WalletAppConfig * Move helper methods to create data dstructures in a project to their respective AppConfig file
This commit is contained in:
parent
3912a02f53
commit
dec503f561
@ -1,7 +1,6 @@
|
||||
package org.bitcoins.server
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import java.nio.file.{Files, Paths}
|
||||
import java.nio.file.Paths
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.http.scaladsl.Http
|
||||
@ -14,22 +13,24 @@ import org.bitcoins.chain.models.{
|
||||
CompactFilterHeaderDAO
|
||||
}
|
||||
import org.bitcoins.core.Core
|
||||
import org.bitcoins.core.api.{ChainQueryApi, FeeRateApi}
|
||||
import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil}
|
||||
import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil, NetworkUtil}
|
||||
import org.bitcoins.db.AppConfig
|
||||
import org.bitcoins.feeprovider.BitcoinerLiveFeeRateProvider
|
||||
import org.bitcoins.keymanager.KeyManagerInitializeError
|
||||
import org.bitcoins.keymanager.bip39.{BIP39KeyManager, BIP39LockedKeyManager}
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
import org.bitcoins.node.models.Peer
|
||||
import org.bitcoins.node._
|
||||
import org.bitcoins.wallet.Wallet
|
||||
import org.bitcoins.node.{
|
||||
Node,
|
||||
NodeCallbacks,
|
||||
OnBlockHeadersReceived,
|
||||
OnBlockReceived,
|
||||
OnCompactFiltersReceived,
|
||||
OnTxReceived,
|
||||
SpvNode
|
||||
}
|
||||
import org.bitcoins.wallet.api._
|
||||
import org.bitcoins.wallet.config.WalletAppConfig
|
||||
import org.bitcoins.wallet.models.AccountDAO
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.{Await, ExecutionContext, Future, Promise}
|
||||
import scala.concurrent.{ExecutionContext, Future, Promise}
|
||||
|
||||
object Main extends App with BitcoinSLogger {
|
||||
|
||||
@ -69,7 +70,8 @@ object Main extends App with BitcoinSLogger {
|
||||
implicit val chainConf: ChainAppConfig = conf.chainConf
|
||||
|
||||
val peerSocket =
|
||||
parseInetSocketAddress(nodeConf.peers.head, nodeConf.network.port)
|
||||
NetworkUtil.parseInetSocketAddress(nodeConf.peers.head,
|
||||
nodeConf.network.port)
|
||||
val peer = Peer.fromSocket(peerSocket)
|
||||
val bip39PasswordOpt = None //todo need to prompt user for this
|
||||
|
||||
@ -83,7 +85,7 @@ object Main extends App with BitcoinSLogger {
|
||||
|
||||
//get a node that isn't started
|
||||
val uninitializedNodeF = configInitializedF.flatMap { _ =>
|
||||
createNode(peer)(nodeConf, chainConf, system)
|
||||
nodeConf.createNode(peer)(chainConf, system)
|
||||
}
|
||||
|
||||
//get our wallet
|
||||
@ -91,10 +93,10 @@ object Main extends App with BitcoinSLogger {
|
||||
_ <- configInitializedF
|
||||
uninitializedNode <- uninitializedNodeF
|
||||
chainApi <- chainApiF
|
||||
wallet <- createWallet(uninitializedNode,
|
||||
chainApi,
|
||||
BitcoinerLiveFeeRateProvider(60),
|
||||
bip39PasswordOpt)
|
||||
wallet <- walletConf.createWallet(uninitializedNode,
|
||||
chainApi,
|
||||
BitcoinerLiveFeeRateProvider(60),
|
||||
bip39PasswordOpt)
|
||||
} yield wallet
|
||||
|
||||
//add callbacks to our unitialized node
|
||||
@ -156,83 +158,6 @@ object Main extends App with BitcoinSLogger {
|
||||
//start everything!
|
||||
runMain()
|
||||
|
||||
/** Checks if the user already has a wallet */
|
||||
private def hasWallet()(
|
||||
implicit walletConf: WalletAppConfig,
|
||||
ec: ExecutionContext): Future[Boolean] = {
|
||||
val walletDB = walletConf.dbPath resolve walletConf.dbName
|
||||
val hdCoin = walletConf.defaultAccount.coin
|
||||
if (Files.exists(walletDB) && walletConf.seedExists()) {
|
||||
AccountDAO().read((hdCoin, 0)).map(_.isDefined)
|
||||
} else {
|
||||
Future.successful(false)
|
||||
}
|
||||
}
|
||||
|
||||
private def createNode(peer: Peer)(
|
||||
implicit nodeConf: NodeAppConfig,
|
||||
chainConf: ChainAppConfig,
|
||||
system: ActorSystem): Future[Node] = {
|
||||
if (nodeConf.isSPVEnabled) {
|
||||
Future.successful(SpvNode(peer, nodeConf, chainConf, system))
|
||||
} else if (nodeConf.isNeutrinoEnabled) {
|
||||
Future.successful(NeutrinoNode(peer, nodeConf, chainConf, system))
|
||||
} else {
|
||||
Future.failed(
|
||||
new RuntimeException("Neither Neutrino nor SPV mode is enabled."))
|
||||
}
|
||||
}
|
||||
|
||||
private def createWallet(
|
||||
nodeApi: Node,
|
||||
chainQueryApi: ChainQueryApi,
|
||||
feeRateApi: FeeRateApi,
|
||||
bip39PasswordOpt: Option[String])(
|
||||
implicit walletConf: WalletAppConfig,
|
||||
system: ActorSystem): Future[WalletApi] = {
|
||||
import system.dispatcher
|
||||
hasWallet().flatMap { walletExists =>
|
||||
if (walletExists) {
|
||||
logger.info(s"Using pre-existing wallet")
|
||||
|
||||
// TODO change me when we implement proper password handling
|
||||
BIP39LockedKeyManager.unlock(BIP39KeyManager.badPassphrase,
|
||||
bip39PasswordOpt,
|
||||
walletConf.kmParams) match {
|
||||
case Right(km) =>
|
||||
val wallet =
|
||||
Wallet(km, nodeApi, chainQueryApi, feeRateApi, km.creationTime)
|
||||
Future.successful(wallet)
|
||||
case Left(err) =>
|
||||
error(err)
|
||||
}
|
||||
} else {
|
||||
logger.info(s"Initializing key manager")
|
||||
val bip39PasswordOpt = None
|
||||
val keyManagerE: Either[KeyManagerInitializeError, BIP39KeyManager] =
|
||||
BIP39KeyManager.initialize(kmParams = walletConf.kmParams,
|
||||
bip39PasswordOpt = bip39PasswordOpt)
|
||||
|
||||
val keyManager = keyManagerE match {
|
||||
case Right(keyManager) => keyManager
|
||||
case Left(err) =>
|
||||
error(err)
|
||||
}
|
||||
|
||||
logger.info(s"Creating new wallet")
|
||||
val unInitializedWallet =
|
||||
Wallet(keyManager,
|
||||
nodeApi,
|
||||
chainQueryApi,
|
||||
feeRateApi,
|
||||
keyManager.creationTime)
|
||||
|
||||
Wallet.initialize(wallet = unInitializedWallet,
|
||||
bip39PasswordOpt = bip39PasswordOpt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def createCallbacks(wallet: WalletApi)(
|
||||
implicit nodeConf: NodeAppConfig,
|
||||
ec: ExecutionContext): Future[NodeCallbacks] = {
|
||||
@ -287,41 +212,6 @@ object Main extends App with BitcoinSLogger {
|
||||
}
|
||||
}
|
||||
|
||||
/** Log the given message, shut down the actor system and quit. */
|
||||
private def error(message: Any)(implicit system: ActorSystem): Nothing = {
|
||||
logger.error(s"FATAL: $message")
|
||||
logger.error(s"Shutting down actor system")
|
||||
Await.result(system.terminate(), 10.seconds)
|
||||
logger.error("Actor system terminated")
|
||||
logger.error(s"Exiting")
|
||||
sys.error(message.toString())
|
||||
}
|
||||
|
||||
private def parseInetSocketAddress(
|
||||
address: String,
|
||||
defaultPort: Int): InetSocketAddress = {
|
||||
|
||||
def parsePort(port: String): Int = {
|
||||
lazy val errorMsg = s"Invalid peer port: $address"
|
||||
try {
|
||||
val res = port.toInt
|
||||
if (res < 0 || res > 0xffff) {
|
||||
throw new RuntimeException(errorMsg)
|
||||
}
|
||||
res
|
||||
} catch {
|
||||
case _: NumberFormatException =>
|
||||
throw new RuntimeException(errorMsg)
|
||||
}
|
||||
}
|
||||
|
||||
address.split(":") match {
|
||||
case Array(host) => new InetSocketAddress(host, defaultPort)
|
||||
case Array(host, port) => new InetSocketAddress(host, parsePort(port))
|
||||
case _ => throw new RuntimeException(s"Invalid peer address: $address")
|
||||
}
|
||||
}
|
||||
|
||||
/** This is needed for migrations V2/V3 on the chain project to re-calculate the total work for the chain */
|
||||
private def runChainWorkCalc()(
|
||||
implicit chainAppConfig: ChainAppConfig,
|
||||
|
35
core/src/main/scala/org/bitcoins/core/util/NetworkUtil.scala
Normal file
35
core/src/main/scala/org/bitcoins/core/util/NetworkUtil.scala
Normal file
@ -0,0 +1,35 @@
|
||||
package org.bitcoins.core.util
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
|
||||
abstract class NetworkUtil {
|
||||
|
||||
private def parsePort(port: String): Int = {
|
||||
lazy val errorMsg = s"Invalid peer port: $port"
|
||||
try {
|
||||
val res = port.toInt
|
||||
if (res < 0 || res > 0xffff) {
|
||||
throw new RuntimeException(errorMsg)
|
||||
}
|
||||
res
|
||||
} catch {
|
||||
case _: NumberFormatException =>
|
||||
throw new RuntimeException(errorMsg)
|
||||
}
|
||||
}
|
||||
|
||||
/** Parses a string that looks like this to [[java.net.InetSocketAddress]]
|
||||
* "neutrino.testnet3.suredbits.com:18333"
|
||||
* */
|
||||
def parseInetSocketAddress(
|
||||
address: String,
|
||||
defaultPort: Int): InetSocketAddress = {
|
||||
address.split(":") match {
|
||||
case Array(host) => new InetSocketAddress(host, defaultPort)
|
||||
case Array(host, port) => new InetSocketAddress(host, parsePort(port))
|
||||
case _ => throw new RuntimeException(s"Invalid peer address: $address")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object NetworkUtil extends NetworkUtil
|
@ -2,10 +2,14 @@ package org.bitcoins.node.config
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import com.typesafe.config.Config
|
||||
import org.bitcoins.chain.config.ChainAppConfig
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.db.{AppConfig, AppConfigFactory, JdbcProfileComponent}
|
||||
import org.bitcoins.node.{NeutrinoNode, Node, SpvNode}
|
||||
import org.bitcoins.node.db.NodeDbManagement
|
||||
import org.bitcoins.node.models.Peer
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
@ -68,6 +72,11 @@ case class NodeAppConfig(
|
||||
0.until(list.size())
|
||||
.foldLeft(Vector.empty[String])((acc, i) => acc :+ list.get(i))
|
||||
}
|
||||
|
||||
/** Creates either a neutrino node or a spv node based on the [[NodeAppConfig]] given */
|
||||
def createNode(peer: Peer)(chainConf: ChainAppConfig, system: ActorSystem): Future[Node] = {
|
||||
NodeAppConfig.createNode(peer)(this,chainConf,system)
|
||||
}
|
||||
}
|
||||
|
||||
object NodeAppConfig extends AppConfigFactory[NodeAppConfig] {
|
||||
@ -81,4 +90,15 @@ object NodeAppConfig extends AppConfigFactory[NodeAppConfig] {
|
||||
useLogbackConf,
|
||||
confs: _*)
|
||||
|
||||
/** Creates either a neutrino node or a spv node based on the [[NodeAppConfig]] given */
|
||||
def createNode(peer: Peer)(implicit nodeConf: NodeAppConfig, chainConf: ChainAppConfig, system: ActorSystem): Future[Node] = {
|
||||
if (nodeConf.isSPVEnabled) {
|
||||
Future.successful(SpvNode(peer, nodeConf, chainConf, system))
|
||||
} else if (nodeConf.isNeutrinoEnabled) {
|
||||
Future.successful(NeutrinoNode(peer, nodeConf, chainConf, system))
|
||||
} else {
|
||||
Future.failed(
|
||||
new RuntimeException("Neither Neutrino nor SPV mode is enabled."))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,20 @@ import java.nio.file.{Files, Path}
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import org.bitcoins.core.api.{ChainQueryApi, FeeRateApi, NodeApi}
|
||||
import org.bitcoins.core.hd._
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.db.{AppConfig, AppConfigFactory, JdbcProfileComponent}
|
||||
import org.bitcoins.keymanager.{KeyManagerParams, WalletStorage}
|
||||
import org.bitcoins.keymanager.bip39.{BIP39KeyManager, BIP39LockedKeyManager}
|
||||
import org.bitcoins.keymanager.{
|
||||
KeyManagerInitializeError,
|
||||
KeyManagerParams,
|
||||
WalletStorage
|
||||
}
|
||||
import org.bitcoins.wallet.{Wallet, WalletLogger}
|
||||
import org.bitcoins.wallet.api.WalletApi
|
||||
import org.bitcoins.wallet.db.WalletDbManagement
|
||||
import org.bitcoins.wallet.models.AccountDAO
|
||||
|
||||
import scala.concurrent.duration.{DurationInt, FiniteDuration}
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
@ -125,9 +134,38 @@ case class WalletAppConfig(
|
||||
5.second
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks if the following exist
|
||||
* 1. A wallet exists
|
||||
* 2. seed exists
|
||||
* 3. The account exists */
|
||||
def hasWallet()(implicit ec: ExecutionContext): Future[Boolean] = {
|
||||
val walletDB = dbPath.resolve(dbName)
|
||||
val hdCoin = defaultAccount.coin
|
||||
if (Files.exists(walletDB) && seedExists()) {
|
||||
AccountDAO()(ec, this).read((hdCoin, 0)).map(_.isDefined)
|
||||
} else {
|
||||
Future.successful(false)
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a wallet based on this [[WalletAppConfig]] */
|
||||
def createWallet(
|
||||
nodeApi: NodeApi,
|
||||
chainQueryApi: ChainQueryApi,
|
||||
feeRateApi: FeeRateApi,
|
||||
bip39PasswordOpt: Option[String])(
|
||||
implicit ec: ExecutionContext): Future[WalletApi] = {
|
||||
WalletAppConfig.createWallet(nodeApi = nodeApi,
|
||||
chainQueryApi = chainQueryApi,
|
||||
feeRateApi = feeRateApi,
|
||||
bip39PasswordOpt = bip39PasswordOpt)(this, ec)
|
||||
}
|
||||
}
|
||||
|
||||
object WalletAppConfig extends AppConfigFactory[WalletAppConfig] {
|
||||
object WalletAppConfig
|
||||
extends AppConfigFactory[WalletAppConfig]
|
||||
with WalletLogger {
|
||||
|
||||
/** Constructs a wallet configuration from the default Bitcoin-S
|
||||
* data directory and given list of configuration overrides.
|
||||
@ -137,4 +175,53 @@ object WalletAppConfig extends AppConfigFactory[WalletAppConfig] {
|
||||
useLogbackConf: Boolean,
|
||||
confs: Vector[Config])(implicit ec: ExecutionContext): WalletAppConfig =
|
||||
WalletAppConfig(datadir, useLogbackConf, confs: _*)
|
||||
|
||||
/** Creates a wallet based on the given [[WalletAppConfig]] */
|
||||
def createWallet(
|
||||
nodeApi: NodeApi,
|
||||
chainQueryApi: ChainQueryApi,
|
||||
feeRateApi: FeeRateApi,
|
||||
bip39PasswordOpt: Option[String])(
|
||||
implicit walletConf: WalletAppConfig,
|
||||
ec: ExecutionContext): Future[WalletApi] = {
|
||||
walletConf.hasWallet().flatMap { walletExists =>
|
||||
if (walletExists) {
|
||||
logger.info(s"Using pre-existing wallet")
|
||||
// TODO change me when we implement proper password handling
|
||||
BIP39LockedKeyManager.unlock(BIP39KeyManager.badPassphrase,
|
||||
bip39PasswordOpt,
|
||||
walletConf.kmParams) match {
|
||||
case Right(km) =>
|
||||
val wallet =
|
||||
Wallet(km, nodeApi, chainQueryApi, feeRateApi, km.creationTime)
|
||||
Future.successful(wallet)
|
||||
case Left(err) =>
|
||||
sys.error(s"Error initializing key manager, err=${err}")
|
||||
}
|
||||
} else {
|
||||
logger.info(s"Initializing key manager")
|
||||
val bip39PasswordOpt = None
|
||||
val keyManagerE: Either[KeyManagerInitializeError, BIP39KeyManager] =
|
||||
BIP39KeyManager.initialize(kmParams = walletConf.kmParams,
|
||||
bip39PasswordOpt = bip39PasswordOpt)
|
||||
|
||||
val keyManager = keyManagerE match {
|
||||
case Right(keyManager) => keyManager
|
||||
case Left(err) =>
|
||||
sys.error(s"Error initializing key manager, err=${err}")
|
||||
}
|
||||
|
||||
logger.info(s"Creating new wallet")
|
||||
val unInitializedWallet =
|
||||
Wallet(keyManager,
|
||||
nodeApi,
|
||||
chainQueryApi,
|
||||
feeRateApi,
|
||||
keyManager.creationTime)
|
||||
|
||||
Wallet.initialize(wallet = unInitializedWallet,
|
||||
bip39PasswordOpt = bip39PasswordOpt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user