mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 09:52:09 +01:00
This creates a subtype BIP39KeyManager and moves all existing KeyMana… (#988)
* This creates a subtype BIP39KeyManager and moves all existing KeyManager functionality to that subtype. We leave a empty 'KeyManager' trait for now * Fix website docs
This commit is contained in:
parent
31a233f0c5
commit
c3fb7c9a67
@ -6,6 +6,7 @@ import java.nio.file.Files
|
||||
import akka.actor.ActorSystem
|
||||
import org.bitcoins.chain.config.ChainAppConfig
|
||||
import org.bitcoins.core.api.ChainQueryApi
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import org.bitcoins.keymanager.{KeyManager, KeyManagerInitializeError}
|
||||
import org.bitcoins.node.config.NodeAppConfig
|
||||
import org.bitcoins.node.models.Peer
|
||||
@ -99,14 +100,14 @@ object Main extends App {
|
||||
val locked = LockedWallet(nodeApi, chainQueryApi)
|
||||
|
||||
// TODO change me when we implement proper password handling
|
||||
locked.unlock(KeyManager.badPassphrase) match {
|
||||
locked.unlock(BIP39KeyManager.badPassphrase) match {
|
||||
case Right(wallet) => Future.successful(wallet)
|
||||
case Left(kmError) => error(kmError)
|
||||
}
|
||||
} else {
|
||||
logger.info(s"Initializing key manager")
|
||||
val keyManagerE: Either[KeyManagerInitializeError, KeyManager] =
|
||||
KeyManager.initialize(walletConf.kmParams)
|
||||
val keyManagerE: Either[KeyManagerInitializeError, BIP39KeyManager] =
|
||||
BIP39KeyManager.initialize(walletConf.kmParams)
|
||||
|
||||
val keyManager = keyManagerE match {
|
||||
case Right(keyManager) => keyManager
|
||||
|
@ -111,7 +111,8 @@ val syncF: Future[ChainApi] = configF.flatMap { _ =>
|
||||
|
||||
//initialize our key manager, where we store our keys
|
||||
import org.bitcoins.keymanager._
|
||||
val keyManager = KeyManager.initialize(walletConfig.kmParams).getOrElse {
|
||||
import org.bitcoins.keymanager.bip39._
|
||||
val keyManager = BIP39KeyManager.initialize(walletConfig.kmParams).getOrElse {
|
||||
throw new RuntimeException(s"Failed to initalize key manager")
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,11 @@ title: Key Manager
|
||||
|
||||
The key manager module's goal is to encapusulate all private key interactions with the [wallet](../applications/wallet.md) project.
|
||||
|
||||
As of this writing, the wallet just delegates storage of the encrypted mnemonic seed to the key manager project. Over the long run, we want to make it so that the wallet project needs to communicate with the key-manager to access private keys.
|
||||
As of this writing, there is only one type of `KeyManager` - [`BIP39KeyManager`](../../key-manager/src/main/scala/org/bitcoins/keymanager/bip39/BIP39KeyManager.scala).
|
||||
|
||||
The [`BIP39KeyManager`](../../key-manager/src/main/scala/org/bitcoins/keymanager/bip39/BIP39KeyManager.scala) stores a [`MnemonicCode`](../../core/src/main/scala/org/bitcoins/core/crypto/MnemonicCode.scala) on disk which can be decrypted and used as a hot wallet.
|
||||
|
||||
Over the long run, we want to make it so that the wallet project needs to communicate with the key-manager to access private keys.
|
||||
|
||||
This means that ALL SIGNING should be done inside of the key-manager, and private keys should not leave the key manager.
|
||||
|
||||
@ -58,6 +62,8 @@ import org.bitcoins.core.hd._
|
||||
|
||||
import org.bitcoins.keymanager._
|
||||
|
||||
import org.bitcoins.keymanager.bip39._
|
||||
|
||||
import java.nio.file._
|
||||
|
||||
//this will create a temp directory with the prefix 'key-manager-example` that will
|
||||
@ -72,7 +78,7 @@ val network = RegTest
|
||||
|
||||
val kmParams = KeyManagerParams(seedPath, purpose, network)
|
||||
|
||||
val km = KeyManager.initializeWithMnemonic(mnemonic, kmParams)
|
||||
val km = BIP39KeyManager.initializeWithMnemonic(mnemonic, kmParams)
|
||||
|
||||
val rootXPub = km.right.get.getRootXPub
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
package org.bitcoins.keymanager
|
||||
package org.bitcoins.keymanager.bip39
|
||||
|
||||
import org.bitcoins.core.config.MainNet
|
||||
import org.bitcoins.core.crypto.{DoubleSha256DigestBE, MnemonicCode}
|
||||
import org.bitcoins.core.hd._
|
||||
import org.bitcoins.keymanager._
|
||||
import scodec.bits.BitVector
|
||||
|
||||
class KeyManagerTest extends KeyManagerUnitTest {
|
||||
class BIP39KeyManagerTest extends KeyManagerUnitTest {
|
||||
val purpose = HDPurposes.Legacy
|
||||
//this is taken from 'trezor-addresses.json' which give us test cases that conform with trezor
|
||||
val mnemonicStr ="stage boring net gather radar radio arrest eye ask risk girl country"
|
||||
@ -45,11 +46,11 @@ class KeyManagerTest extends KeyManagerUnitTest {
|
||||
|
||||
it must "initialize a key manager to the same xpub if we call constructor directly or use CreateKeyManagerApi" in {
|
||||
val kmParams = buildParams()
|
||||
val direct = KeyManager(mnemonic, kmParams)
|
||||
val direct = BIP39KeyManager(mnemonic, kmParams)
|
||||
|
||||
val directXpub = direct.getRootXPub
|
||||
|
||||
val api = KeyManager.initializeWithEntropy(mnemonic.toEntropy, kmParams).right.get
|
||||
val api = BIP39KeyManager.initializeWithEntropy(mnemonic.toEntropy, kmParams).right.get
|
||||
|
||||
val apiXpub = api.getRootXPub
|
||||
|
||||
@ -62,7 +63,7 @@ class KeyManagerTest extends KeyManagerUnitTest {
|
||||
|
||||
it must "return a mnemonic not found if we have not initialized the key manager" in {
|
||||
val kmParams = buildParams()
|
||||
val kmE = KeyManager.fromParams(kmParams, KeyManager.badPassphrase)
|
||||
val kmE = BIP39KeyManager.fromParams(kmParams, BIP39KeyManager.badPassphrase)
|
||||
|
||||
assert(kmE == Left(ReadMnemonicError.NotFoundError))
|
||||
}
|
||||
@ -79,7 +80,7 @@ class KeyManagerTest extends KeyManagerUnitTest {
|
||||
val badEntropy = BitVector.empty
|
||||
|
||||
|
||||
val init = KeyManager.initializeWithEntropy(badEntropy, buildParams())
|
||||
val init = BIP39KeyManager.initializeWithEntropy(badEntropy, buildParams())
|
||||
|
||||
assert(init == Left(InitializeKeyManagerError.BadEntropy))
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
package org.bitcoins.keymanager
|
||||
package org.bitcoins.keymanager.bip39
|
||||
|
||||
import org.bitcoins.core.crypto.AesPassword
|
||||
import org.bitcoins.keymanager.{KeyManagerTestUtil, KeyManagerUnitTest, KeyManagerUnlockError}
|
||||
|
||||
class LockedKeyManagerTest extends KeyManagerUnitTest {
|
||||
class BIP39LockedKeyManagerTest extends KeyManagerUnitTest {
|
||||
|
||||
it must "be able to read a locked mnemonic from disk" in {
|
||||
val km = withInitializedKeyManager()
|
||||
|
||||
val unlockedKm = LockedKeyManager.unlock(KeyManagerTestUtil.badPassphrase, km.kmParams) match {
|
||||
val unlockedKm = BIP39LockedKeyManager.unlock(KeyManagerTestUtil.badPassphrase, km.kmParams) match {
|
||||
case Right(km) => km
|
||||
case Left(err) => fail(s"Failed to unlock key manager ${err}")
|
||||
}
|
||||
@ -19,7 +20,7 @@ class LockedKeyManagerTest extends KeyManagerUnitTest {
|
||||
it must "fail to read bad json in the seed file" in {
|
||||
val km = withInitializedKeyManager()
|
||||
val badPassword = AesPassword.fromString("other bad password").get
|
||||
LockedKeyManager.unlock(passphrase = badPassword, kmParams = km.kmParams) match {
|
||||
BIP39LockedKeyManager.unlock(passphrase = badPassword, kmParams = km.kmParams) match {
|
||||
case Left(KeyManagerUnlockError.BadPassword) => succeed
|
||||
case result @ (Left(_) | Right(_)) =>
|
||||
fail(s"Expected to fail test with ${KeyManagerUnlockError.BadPassword} got ${result}")
|
||||
@ -33,7 +34,7 @@ class LockedKeyManagerTest extends KeyManagerUnitTest {
|
||||
|
||||
val badPath = km.kmParams.copy(seedPath = badSeedPath)
|
||||
val badPassword = AesPassword.fromString("other bad password").get
|
||||
LockedKeyManager.unlock(badPassword, badPath) match {
|
||||
BIP39LockedKeyManager.unlock(badPassword, badPath) match {
|
||||
case Left(KeyManagerUnlockError.MnemonicNotFound) => succeed
|
||||
case result @ (Left(_) | Right(_)) =>
|
||||
fail(s"Expected to fail test with ${KeyManagerUnlockError.MnemonicNotFound} got ${result}")
|
@ -16,14 +16,13 @@ import scodec.bits.BitVector
|
||||
* can write it down. They should also be prompted
|
||||
* to confirm at least parts of the code.
|
||||
*/
|
||||
trait KeyManagerCreateApi {
|
||||
trait KeyManagerCreateApi[T <: KeyManager] {
|
||||
|
||||
/**
|
||||
* $initialize
|
||||
*/
|
||||
final def initialize(kmParams: KeyManagerParams): Either[
|
||||
KeyManagerInitializeError,
|
||||
KeyManager] =
|
||||
final def initialize(
|
||||
kmParams: KeyManagerParams): Either[KeyManagerInitializeError, T] =
|
||||
initializeWithEntropy(entropy = MnemonicCode.getEntropy256Bits, kmParams)
|
||||
|
||||
/**
|
||||
@ -31,7 +30,7 @@ trait KeyManagerCreateApi {
|
||||
*/
|
||||
def initializeWithEntropy(
|
||||
entropy: BitVector,
|
||||
kmParams: KeyManagerParams): Either[KeyManagerInitializeError, KeyManager]
|
||||
kmParams: KeyManagerParams): Either[KeyManagerInitializeError, T]
|
||||
|
||||
/**
|
||||
* Helper method to initialize a [[KeyManagerCreate$ KeyManager]] with a [[MnemonicCode MnemonicCode]]
|
||||
@ -42,9 +41,7 @@ trait KeyManagerCreateApi {
|
||||
*/
|
||||
final def initializeWithMnemonic(
|
||||
mnemonicCode: MnemonicCode,
|
||||
kmParams: KeyManagerParams): Either[
|
||||
KeyManagerInitializeError,
|
||||
KeyManager] = {
|
||||
kmParams: KeyManagerParams): Either[KeyManagerInitializeError, T] = {
|
||||
val entropy = mnemonicCode.toEntropy
|
||||
initializeWithEntropy(entropy = entropy, kmParams)
|
||||
}
|
||||
|
@ -0,0 +1,145 @@
|
||||
package org.bitcoins.keymanager.bip39
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
import org.bitcoins.core.compat.{CompatEither, CompatLeft, CompatRight}
|
||||
import org.bitcoins.core.crypto._
|
||||
import org.bitcoins.core.hd.{HDAccount, HDPath}
|
||||
import org.bitcoins.core.util.BitcoinSLogger
|
||||
import org.bitcoins.keymanager.util.HDUtil
|
||||
import org.bitcoins.keymanager._
|
||||
import scodec.bits.BitVector
|
||||
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
/**
|
||||
* This is a key manager implementation meant to represent an in memory
|
||||
* BIP39 key manager
|
||||
*
|
||||
* @param mnemonic the mnemonic seed used for this wallet
|
||||
* @param kmParams the parameters used to generate the right keychain
|
||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||
*/
|
||||
case class BIP39KeyManager(
|
||||
private val mnemonic: MnemonicCode,
|
||||
kmParams: KeyManagerParams)
|
||||
extends KeyManager {
|
||||
|
||||
private val seed = BIP39Seed.fromMnemonic(mnemonic = mnemonic,
|
||||
password = BIP39Seed.EMPTY_PASSWORD)
|
||||
|
||||
private val privVersion: ExtKeyPrivVersion =
|
||||
HDUtil.getXprivVersion(kmParams.purpose, kmParams.network)
|
||||
|
||||
private val rootExtPrivKey = seed.toExtPrivateKey(privVersion)
|
||||
|
||||
/** Converts a non-sensitive DB representation of a UTXO into
|
||||
* a signable (and sensitive) real-world UTXO
|
||||
*/
|
||||
def toSign(privKeyPath: HDPath): Sign = {
|
||||
val xpriv =
|
||||
rootExtPrivKey.deriveChildPrivKey(privKeyPath)
|
||||
|
||||
xpriv
|
||||
}
|
||||
|
||||
def deriveXPub(account: HDAccount): Try[ExtPublicKey] = {
|
||||
rootExtPrivKey.deriveChildPubKey(account)
|
||||
}
|
||||
|
||||
/** Returns the root [[ExtPublicKey]] */
|
||||
def getRootXPub: ExtPublicKey = {
|
||||
rootExtPrivKey.extPublicKey
|
||||
}
|
||||
}
|
||||
|
||||
object BIP39KeyManager
|
||||
extends KeyManagerCreateApi[BIP39KeyManager]
|
||||
with BitcoinSLogger {
|
||||
val badPassphrase = AesPassword.fromString("bad-password").get
|
||||
|
||||
/** Initializes the mnemonic seed and saves it to file */
|
||||
override def initializeWithEntropy(
|
||||
entropy: BitVector,
|
||||
kmParams: KeyManagerParams): Either[
|
||||
KeyManagerInitializeError,
|
||||
BIP39KeyManager] = {
|
||||
val seedPath = kmParams.seedPath
|
||||
logger.info(s"Initializing wallet with seedPath=${seedPath}")
|
||||
|
||||
if (Files.notExists(seedPath)) {
|
||||
logger.info(
|
||||
s"Seed path parent directory does not exist, creating ${seedPath.getParent}")
|
||||
Files.createDirectories(seedPath.getParent)
|
||||
}
|
||||
|
||||
val mnemonicT = Try(MnemonicCode.fromEntropy(entropy))
|
||||
val mnemonicE: CompatEither[KeyManagerInitializeError, MnemonicCode] =
|
||||
mnemonicT match {
|
||||
case Success(mnemonic) =>
|
||||
logger.info(s"Created mnemonic from entropy")
|
||||
CompatEither(Right(mnemonic))
|
||||
case Failure(err) =>
|
||||
logger.error(s"Could not create mnemonic from entropy! $err")
|
||||
CompatEither(Left(InitializeKeyManagerError.BadEntropy))
|
||||
}
|
||||
|
||||
val encryptedMnemonicE: CompatEither[
|
||||
KeyManagerInitializeError,
|
||||
EncryptedMnemonic] =
|
||||
mnemonicE.map { EncryptedMnemonicHelper.encrypt(_, badPassphrase) }
|
||||
|
||||
val writeToDiskE: CompatEither[KeyManagerInitializeError, KeyManager] =
|
||||
for {
|
||||
mnemonic <- mnemonicE
|
||||
encrypted <- encryptedMnemonicE
|
||||
_ = {
|
||||
val mnemonicPath =
|
||||
WalletStorage.writeMnemonicToDisk(seedPath, encrypted)
|
||||
logger.info(s"Saved encrypted wallet mnemonic to $mnemonicPath")
|
||||
}
|
||||
|
||||
} yield BIP39KeyManager(mnemonic = mnemonic, kmParams = kmParams)
|
||||
|
||||
//verify we can unlock it for a sanity check
|
||||
val unlocked = BIP39LockedKeyManager.unlock(badPassphrase, kmParams)
|
||||
|
||||
val biasedFinalE: CompatEither[KeyManagerInitializeError, BIP39KeyManager] =
|
||||
for {
|
||||
kmBeforeWrite <- writeToDiskE
|
||||
invariant <- unlocked match {
|
||||
case Right(unlockedKeyManager) =>
|
||||
require(kmBeforeWrite == unlockedKeyManager,
|
||||
s"We could not read the key manager we just wrote!")
|
||||
CompatRight(unlockedKeyManager)
|
||||
|
||||
case Left(err) =>
|
||||
CompatLeft(InitializeKeyManagerError.FailedToReadWrittenSeed(err))
|
||||
}
|
||||
} yield {
|
||||
invariant
|
||||
}
|
||||
|
||||
biasedFinalE match {
|
||||
case CompatRight(initSuccess) =>
|
||||
logger.info(s"Successfully initialized wallet")
|
||||
Right(initSuccess)
|
||||
case CompatLeft(err) =>
|
||||
logger.error(s"Failed to initialize key manager with err=${err}")
|
||||
Left(err)
|
||||
}
|
||||
}
|
||||
|
||||
/** Reads the key manager from disk and decrypts it with the given password */
|
||||
def fromParams(
|
||||
kmParams: KeyManagerParams,
|
||||
password: AesPassword): Either[ReadMnemonicError, BIP39KeyManager] = {
|
||||
val mnemonicCodeE =
|
||||
WalletStorage.decryptMnemonicFromDisk(kmParams.seedPath, password)
|
||||
|
||||
mnemonicCodeE match {
|
||||
case Right(mnemonic) => Right(new BIP39KeyManager(mnemonic, kmParams))
|
||||
case Left(v) => Left(v)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.bitcoins.keymanager
|
||||
package org.bitcoins.keymanager.bip39
|
||||
|
||||
import org.bitcoins.core.crypto.AesPassword
|
||||
import org.bitcoins.core.util.BitcoinSLogger
|
||||
@ -6,9 +6,10 @@ import org.bitcoins.keymanager.ReadMnemonicError.{
|
||||
DecryptionError,
|
||||
JsonParsingError
|
||||
}
|
||||
import org.bitcoins.keymanager._
|
||||
|
||||
/** Represents a */
|
||||
object LockedKeyManager extends BitcoinSLogger {
|
||||
object BIP39LockedKeyManager extends BitcoinSLogger {
|
||||
|
||||
/**
|
||||
* Unlock the wallet by decrypting the [[EncryptedMnemonic]] seed
|
||||
@ -16,15 +17,15 @@ object LockedKeyManager extends BitcoinSLogger {
|
||||
* @param kmParams parameters needed to create the key manager
|
||||
*
|
||||
* */
|
||||
def unlock(
|
||||
passphrase: AesPassword,
|
||||
kmParams: KeyManagerParams): Either[KeyManagerUnlockError, KeyManager] = {
|
||||
def unlock(passphrase: AesPassword, kmParams: KeyManagerParams): Either[
|
||||
KeyManagerUnlockError,
|
||||
BIP39KeyManager] = {
|
||||
logger.debug(s"Trying to unlock wallet with seedPath=${kmParams.seedPath}")
|
||||
val resultE =
|
||||
WalletStorage.decryptMnemonicFromDisk(kmParams.seedPath, passphrase)
|
||||
resultE match {
|
||||
case Right(mnemonicCode) =>
|
||||
Right(new KeyManager(mnemonicCode, kmParams))
|
||||
Right(new BIP39KeyManager(mnemonicCode, kmParams))
|
||||
case Left(result) =>
|
||||
result match {
|
||||
case DecryptionError =>
|
@ -3,6 +3,7 @@ package org.bitcoins.keymanager
|
||||
import java.nio.file.Path
|
||||
|
||||
import org.bitcoins.core.crypto.AesPassword
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
|
||||
object KeyManagerTestUtil {
|
||||
@ -14,5 +15,5 @@ object KeyManagerTestUtil {
|
||||
.resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
|
||||
}
|
||||
|
||||
val badPassphrase: AesPassword = KeyManager.badPassphrase
|
||||
val badPassphrase: AesPassword = BIP39KeyManager.badPassphrase
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package org.bitcoins.keymanager
|
||||
import org.bitcoins.core.config.Networks
|
||||
import org.bitcoins.core.crypto.MnemonicCode
|
||||
import org.bitcoins.core.hd.HDPurposes
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import org.bitcoins.testkit.util.BitcoinSUnitTest
|
||||
import org.scalacheck.Gen
|
||||
import scodec.bits.BitVector
|
||||
@ -18,8 +19,8 @@ trait KeyManagerUnitTest extends BitcoinSUnitTest {
|
||||
|
||||
def withInitializedKeyManager(
|
||||
kmParams: KeyManagerParams = createKeyManagerParams(),
|
||||
entropy: BitVector = MnemonicCode.getEntropy256Bits): KeyManager = {
|
||||
val kmResult = KeyManager.initializeWithEntropy(
|
||||
entropy: BitVector = MnemonicCode.getEntropy256Bits): BIP39KeyManager = {
|
||||
val kmResult = BIP39KeyManager.initializeWithEntropy(
|
||||
entropy = entropy,
|
||||
kmParams = kmParams
|
||||
)
|
||||
|
@ -10,6 +10,7 @@ import org.bitcoins.core.protocol.BlockStamp
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.db.AppConfig
|
||||
import org.bitcoins.keymanager.KeyManager
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.server.BitcoinSAppConfig._
|
||||
@ -192,8 +193,8 @@ object BitcoinSWalletTest extends WalletLogger {
|
||||
bitcoind: BitcoindRpcClient)
|
||||
|
||||
private def createNewKeyManager()(
|
||||
implicit config: BitcoinSAppConfig): KeyManager = {
|
||||
val keyManagerE = KeyManager.initialize(config.walletConf.kmParams)
|
||||
implicit config: BitcoinSAppConfig): BIP39KeyManager = {
|
||||
val keyManagerE = BIP39KeyManager.initialize(config.walletConf.kmParams)
|
||||
keyManagerE match {
|
||||
case Right(keyManager) => keyManager
|
||||
case Left(err) =>
|
||||
@ -208,7 +209,7 @@ object BitcoinSWalletTest extends WalletLogger {
|
||||
* or account type.
|
||||
*/
|
||||
private def createNewWallet(
|
||||
keyManager: KeyManager,
|
||||
keyManager: BIP39KeyManager,
|
||||
extraConfig: Option[Config],
|
||||
nodeApi: NodeApi,
|
||||
chainQueryApi: ChainQueryApi)(
|
||||
|
@ -7,6 +7,7 @@ import org.bitcoins.core.hd.HDChainType.{Change, External}
|
||||
import org.bitcoins.core.hd._
|
||||
import org.bitcoins.core.protocol.BitcoinAddress
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import org.bitcoins.keymanager.{KeyManager, KeyManagerParams}
|
||||
import org.bitcoins.rpc.serializers.JsonSerializers._
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
@ -135,7 +136,7 @@ class TrezorAddressTest extends BitcoinSWalletTest with EmptyFixture {
|
||||
}
|
||||
|
||||
private def getWallet(config: WalletAppConfig)(implicit ec: ExecutionContext): Future[Wallet] = {
|
||||
val kmE = KeyManager.initializeWithEntropy(mnemonic.toEntropy, config.kmParams)
|
||||
val kmE = BIP39KeyManager.initializeWithEntropy(mnemonic.toEntropy, config.kmParams)
|
||||
kmE match {
|
||||
case Left(err) => Future.failed(new RuntimeException(s"Failed to initialize km with err=${err}"))
|
||||
case Right(km) =>
|
||||
|
@ -10,6 +10,7 @@ import org.bitcoins.core.protocol.transaction._
|
||||
import org.bitcoins.core.wallet.builder.BitcoinTxBuilder
|
||||
import org.bitcoins.core.wallet.fee.FeeUnit
|
||||
import org.bitcoins.core.wallet.utxo.BitcoinUTXOSpendingInfo
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import org.bitcoins.keymanager.util.HDUtil
|
||||
import org.bitcoins.keymanager.{KeyManager, KeyManagerParams}
|
||||
import org.bitcoins.wallet.api._
|
||||
@ -141,7 +142,7 @@ sealed abstract class Wallet extends LockedWallet with UnlockedWalletApi {
|
||||
object Wallet extends WalletLogger {
|
||||
|
||||
private case class WalletImpl(
|
||||
override val keyManager: KeyManager,
|
||||
override val keyManager: BIP39KeyManager,
|
||||
override val nodeApi: NodeApi,
|
||||
override val chainQueryApi: ChainQueryApi
|
||||
)(
|
||||
@ -150,7 +151,7 @@ object Wallet extends WalletLogger {
|
||||
) extends Wallet
|
||||
|
||||
def apply(
|
||||
keyManager: KeyManager,
|
||||
keyManager: BIP39KeyManager,
|
||||
nodeApi: NodeApi,
|
||||
chainQueryApi: ChainQueryApi)(
|
||||
implicit config: WalletAppConfig,
|
||||
@ -159,7 +160,7 @@ object Wallet extends WalletLogger {
|
||||
}
|
||||
|
||||
/** Creates the level 0 account for the given HD purpose */
|
||||
private def createRootAccount(wallet: Wallet, keyManager: KeyManager)(
|
||||
private def createRootAccount(wallet: Wallet, keyManager: BIP39KeyManager)(
|
||||
implicit walletAppConfig: WalletAppConfig,
|
||||
ec: ExecutionContext): Future[AccountDb] = {
|
||||
val coinType = HDUtil.getCoinType(keyManager.kmParams.network)
|
||||
@ -193,7 +194,8 @@ object Wallet extends WalletLogger {
|
||||
//we need to create key manager params for each purpose
|
||||
//and then initialize a key manager to derive the correct xpub
|
||||
val kmParams = wallet.keyManager.kmParams.copy(purpose = purpose)
|
||||
val kmE = KeyManager.fromParams(kmParams, KeyManager.badPassphrase)
|
||||
val kmE =
|
||||
BIP39KeyManager.fromParams(kmParams, BIP39KeyManager.badPassphrase)
|
||||
kmE match {
|
||||
case Right(km) => createRootAccount(wallet = wallet, keyManager = km)
|
||||
case Left(err) =>
|
||||
|
@ -16,6 +16,7 @@ import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
|
||||
import org.bitcoins.core.wallet.fee.FeeUnit
|
||||
import org.bitcoins.keymanager._
|
||||
import org.bitcoins.keymanager.bip39.{BIP39KeyManager, BIP39LockedKeyManager}
|
||||
import org.bitcoins.wallet.Wallet
|
||||
import org.bitcoins.wallet.config.WalletAppConfig
|
||||
import org.bitcoins.wallet.models.{AccountDb, AddressDb, SpendingInfoDb}
|
||||
@ -187,7 +188,7 @@ trait LockedWalletApi extends WalletApi {
|
||||
val kmParams = walletConfig.kmParams
|
||||
|
||||
val unlockedKeyManagerE =
|
||||
LockedKeyManager.unlock(passphrase, kmParams)
|
||||
BIP39LockedKeyManager.unlock(passphrase, kmParams)
|
||||
unlockedKeyManagerE match {
|
||||
case Right(km) =>
|
||||
val w = Wallet(keyManager = km,
|
||||
@ -211,7 +212,7 @@ trait LockedWalletApi extends WalletApi {
|
||||
|
||||
trait UnlockedWalletApi extends LockedWalletApi {
|
||||
|
||||
def keyManager: KeyManager
|
||||
def keyManager: BIP39KeyManager
|
||||
|
||||
/**
|
||||
* Locks the wallet. After this operation is called,
|
||||
|
@ -12,7 +12,7 @@ import org.bitcoins.core.protocol.transaction.{
|
||||
import org.bitcoins.core.script.crypto.HashType
|
||||
import org.bitcoins.core.wallet.utxo.{BitcoinUTXOSpendingInfo, ConditionalPath}
|
||||
import org.bitcoins.db.{DbRowAutoInc, TableAutoInc}
|
||||
import org.bitcoins.keymanager.{KeyManager}
|
||||
import org.bitcoins.keymanager.bip39.BIP39KeyManager
|
||||
import slick.jdbc.SQLiteProfile.api._
|
||||
import slick.lifted.ProvenShape
|
||||
|
||||
@ -128,7 +128,7 @@ sealed trait SpendingInfoDb extends DbRowAutoInc[SpendingInfoDb] {
|
||||
*/
|
||||
def toUTXOSpendingInfo(
|
||||
account: AccountDb,
|
||||
keyManager: KeyManager,
|
||||
keyManager: BIP39KeyManager,
|
||||
network: NetworkParameters): BitcoinUTXOSpendingInfo = {
|
||||
|
||||
val sign: Sign = keyManager.toSign(privKeyPath = privKeyPath)
|
||||
|
Loading…
Reference in New Issue
Block a user