mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-19 05:43:51 +01:00
Multi wallet support for DLC database (#3289)
* Multi wallet support for DLC database * Fix for postgres
This commit is contained in:
parent
5f5f1b2b1a
commit
cfe0c2f0d8
@ -0,0 +1,64 @@
|
||||
package org.bitcoins.dlc.wallet
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import org.bitcoins.core.number.UInt32
|
||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
import org.bitcoins.testkit.keymanager.KeyManagerTestUtil.bip39PasswordOpt
|
||||
import org.bitcoins.testkit.wallet.BitcoinSWalletTest
|
||||
import org.bitcoins.testkit.wallet.BitcoinSWalletTest._
|
||||
import org.bitcoins.testkit.wallet.DLCWalletUtil._
|
||||
import org.bitcoins.testkit.wallet.FundWalletUtil.FundedDLCWallet
|
||||
import org.scalatest.FutureOutcome
|
||||
|
||||
class MultiWalletDLCTest extends BitcoinSWalletTest {
|
||||
|
||||
override type FixtureParam = FundedDLCWallet
|
||||
|
||||
override def withFixture(test: OneArgAsyncTest): FutureOutcome =
|
||||
withFundedDLCWallet(test, getBIP39PasswordOpt())(getFreshConfig)
|
||||
|
||||
it must "create 2 different dlc wallets" in { fundedWallet =>
|
||||
val walletNameConfB =
|
||||
ConfigFactory.parseString(s"bitcoin-s.wallet.walletName = walletB")
|
||||
|
||||
val dbConf =
|
||||
BitcoinSTestAppConfig.configWithEmbeddedDb(project = None, () => pgUrl())
|
||||
|
||||
val dir = BitcoinSTestAppConfig.tmpDir()
|
||||
|
||||
val configB = BitcoinSAppConfig(dir, walletNameConfB.withFallback(dbConf))
|
||||
|
||||
val walletA = fundedWallet.wallet
|
||||
|
||||
val walletBF = BitcoinSWalletTest.createDLCWallet2Accounts(
|
||||
MockNodeApi,
|
||||
MockChainQueryApi,
|
||||
bip39PasswordOpt)(configB, system)
|
||||
|
||||
for {
|
||||
accountA <- walletA.getDefaultAccount()
|
||||
|
||||
walletB <- walletBF
|
||||
accountB <- walletB.getDefaultAccount()
|
||||
|
||||
_ = assert(accountA.xpub != accountB.xpub)
|
||||
|
||||
_ <- walletA.createDLCOffer(sampleContractInfo,
|
||||
half,
|
||||
Some(SatoshisPerVirtualByte.one),
|
||||
UInt32.zero,
|
||||
UInt32.one)
|
||||
dlcsA <- walletA.listDLCs()
|
||||
dlcsB <- walletB.listDLCs()
|
||||
|
||||
// only stop walletB, walletA will be stopped by the fixture
|
||||
_ <- destroyDLCWallet(walletB)
|
||||
} yield {
|
||||
assert(dlcsA.size == 1)
|
||||
assert(dlcsB.isEmpty)
|
||||
assert(dlcsA != dlcsB)
|
||||
}
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ CREATE TABLE "dlc_announcements"
|
||||
"dlc_id" TEXT NOT NULL,
|
||||
"announcement_id" INTEGER NOT NULL,
|
||||
"index" INTEGER NOT NULL,
|
||||
"used" INTEGER, -- if signatures used for execution
|
||||
"used" BOOLEAN, -- if signatures used for execution
|
||||
constraint "pk_announcement_id_index" primary key ("dlc_id", "announcement_id"),
|
||||
constraint "fk_dlc_id" foreign key ("dlc_id") references "global_dlc_data" ("dlc_id") on update NO ACTION on delete NO ACTION,
|
||||
constraint "fk_announcement_id" foreign key ("announcement_id") references "oracle_announcement_data" ("id") on update NO ACTION on delete NO ACTION
|
||||
|
@ -1,18 +1,18 @@
|
||||
package org.bitcoins.dlc.wallet
|
||||
|
||||
import java.nio.file.{Files, Path}
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi
|
||||
import org.bitcoins.core.api.feeprovider.FeeRateApi
|
||||
import org.bitcoins.core.api.node.NodeApi
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.core.wallet.keymanagement.KeyManagerInitializeError
|
||||
import org.bitcoins.db.{AppConfigFactory, DbAppConfig, JdbcProfileComponent}
|
||||
import org.bitcoins.db.DatabaseDriver._
|
||||
import org.bitcoins.db._
|
||||
import org.bitcoins.keymanager.bip39.{BIP39KeyManager, BIP39LockedKeyManager}
|
||||
import org.bitcoins.wallet.config.WalletAppConfig
|
||||
import org.bitcoins.wallet.{Wallet, WalletLogger}
|
||||
|
||||
import java.nio.file._
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
/** Configuration for the Bitcoin-S wallet
|
||||
@ -53,6 +53,35 @@ case class DLCAppConfig(private val directory: Path, private val conf: Config*)(
|
||||
FutureUtil.unit
|
||||
}
|
||||
|
||||
lazy val walletConf: WalletAppConfig =
|
||||
WalletAppConfig(directory, conf: _*)
|
||||
|
||||
lazy val walletNameOpt: Option[String] = walletConf.walletNameOpt
|
||||
|
||||
override lazy val dbPath: Path = {
|
||||
val pathStrOpt =
|
||||
config.getStringOrNone(s"bitcoin-s.$moduleName.db.path")
|
||||
(pathStrOpt, walletNameOpt) match {
|
||||
case (Some(pathStr), Some(walletName)) =>
|
||||
Paths.get(pathStr).resolve(walletName)
|
||||
case (Some(pathStr), None) =>
|
||||
Paths.get(pathStr)
|
||||
case (None, Some(_)) | (None, None) =>
|
||||
sys.error(s"Could not find dbPath for $moduleName.db.path")
|
||||
}
|
||||
}
|
||||
|
||||
override lazy val schemaName: Option[String] = {
|
||||
(driver, walletNameOpt) match {
|
||||
case (PostgreSQL, Some(walletName)) =>
|
||||
Some(s"${moduleName}_$walletName")
|
||||
case (PostgreSQL, None) =>
|
||||
Some(moduleName)
|
||||
case (SQLite, None) | (SQLite, Some(_)) =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def createDLCWallet(
|
||||
nodeApi: NodeApi,
|
||||
chainQueryApi: ChainQueryApi,
|
||||
|
@ -1,8 +1,10 @@
|
||||
package org.bitcoins.testkit.fixtures
|
||||
|
||||
import org.bitcoins.core.util.FutureUtil
|
||||
import org.bitcoins.dlc.wallet.DLCAppConfig
|
||||
import org.bitcoins.dlc.wallet.models._
|
||||
import org.bitcoins.testkit.wallet.BitcoinSWalletTest
|
||||
import org.bitcoins.server.BitcoinSAppConfig
|
||||
import org.bitcoins.testkit.{BitcoinSTestAppConfig, EmbeddedPg}
|
||||
import org.scalatest._
|
||||
|
||||
import scala.concurrent.Future
|
||||
@ -18,9 +20,24 @@ case class DLCDAOs(
|
||||
dlcInputsDAO: DLCFundingInputDAO,
|
||||
dlcSigsDAO: DLCCETSignaturesDAO,
|
||||
dlcRefundSigDAO: DLCRefundSigsDAO,
|
||||
dlcRemoteTxDAO: DLCRemoteTxDAO)
|
||||
dlcRemoteTxDAO: DLCRemoteTxDAO) {
|
||||
|
||||
trait DLCDAOFixture extends BitcoinSWalletTest {
|
||||
val list = Vector(
|
||||
announcementDAO,
|
||||
nonceDAO,
|
||||
dlcDAO,
|
||||
dlcAnnouncementDAO,
|
||||
contractDataDAO,
|
||||
dlcOfferDAO,
|
||||
dlcAcceptDAO,
|
||||
dlcInputsDAO,
|
||||
dlcSigsDAO,
|
||||
dlcRefundSigDAO,
|
||||
dlcRemoteTxDAO
|
||||
)
|
||||
}
|
||||
|
||||
trait DLCDAOFixture extends BitcoinSFixture with EmbeddedPg {
|
||||
|
||||
private lazy val daos: DLCDAOs = {
|
||||
val announcementDAO = OracleAnnouncementDataDAO()
|
||||
@ -51,7 +68,11 @@ trait DLCDAOFixture extends BitcoinSWalletTest {
|
||||
|
||||
final override type FixtureParam = DLCDAOs
|
||||
|
||||
implicit private val dlcConfig: DLCAppConfig = getFreshDLCAppConfig
|
||||
implicit protected val config: BitcoinSAppConfig =
|
||||
BitcoinSTestAppConfig
|
||||
.getNeutrinoWithEmbeddedDbTestConfig(() => pgUrl())
|
||||
|
||||
implicit private val dlcConfig: DLCAppConfig = config.dlcConf
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
super.afterAll()
|
||||
@ -64,7 +85,7 @@ trait DLCDAOFixture extends BitcoinSWalletTest {
|
||||
def dropAll(): Future[Unit] = {
|
||||
val res = for {
|
||||
_ <- dlcConfig.dropTable("flyway_schema_history")
|
||||
_ <- dlcConfig.dropAll()
|
||||
_ <- FutureUtil.sequentially(daos.list.reverse)(dao => dao.deleteAll())
|
||||
} yield ()
|
||||
res.failed.foreach { ex =>
|
||||
ex.printStackTrace()
|
||||
|
@ -54,8 +54,8 @@ trait BitcoinSDualWalletTest extends BitcoinSWalletTest {
|
||||
} yield (walletA, walletB),
|
||||
destroy = { fundedWallets: (FundedDLCWallet, FundedDLCWallet) =>
|
||||
for {
|
||||
_ <- destroyWallet(fundedWallets._1.wallet)
|
||||
_ <- destroyWallet(fundedWallets._2.wallet)
|
||||
_ <- destroyDLCWallet(fundedWallets._1.wallet)
|
||||
_ <- destroyDLCWallet(fundedWallets._2.wallet)
|
||||
} yield ()
|
||||
}
|
||||
)(test)
|
||||
@ -92,10 +92,8 @@ trait BitcoinSDualWalletTest extends BitcoinSWalletTest {
|
||||
},
|
||||
destroy = { dlcWallets: (InitializedDLCWallet, InitializedDLCWallet) =>
|
||||
for {
|
||||
_ <- destroyWallet(dlcWallets._1.wallet)
|
||||
_ <- destroyWallet(dlcWallets._2.wallet)
|
||||
_ <- dlcWallets._1.wallet.dlcConfig.stop()
|
||||
_ <- dlcWallets._2.wallet.dlcConfig.stop()
|
||||
_ <- destroyDLCWallet(dlcWallets._1.wallet)
|
||||
_ <- destroyDLCWallet(dlcWallets._2.wallet)
|
||||
} yield ()
|
||||
}
|
||||
)(test)
|
||||
|
@ -30,7 +30,10 @@ import org.bitcoins.testkit.EmbeddedPg
|
||||
import org.bitcoins.testkit.chain.SyncUtil
|
||||
import org.bitcoins.testkit.fixtures.BitcoinSFixture
|
||||
import org.bitcoins.testkit.keymanager.KeyManagerTestUtil
|
||||
import org.bitcoins.testkit.wallet.FundWalletUtil.FundedWallet
|
||||
import org.bitcoins.testkit.wallet.FundWalletUtil.{
|
||||
FundedDLCWallet,
|
||||
FundedWallet
|
||||
}
|
||||
import org.bitcoins.testkitcore.Implicits.GeneratorOps
|
||||
import org.bitcoins.testkitcore.gen._
|
||||
import org.bitcoins.wallet.config.WalletAppConfig
|
||||
@ -116,6 +119,27 @@ trait BitcoinSWalletTest
|
||||
)(test)
|
||||
}
|
||||
|
||||
/** Creates a wallet that is funded with some bitcoin, this wallet is NOT
|
||||
* peered with a bitcoind so the funds in the wallet are not tied to an
|
||||
* underlying blockchain
|
||||
*/
|
||||
def withFundedDLCWallet(
|
||||
test: OneArgAsyncTest,
|
||||
bip39PasswordOpt: Option[String])(implicit
|
||||
config: BitcoinSAppConfig): FutureOutcome = {
|
||||
makeDependentFixture(
|
||||
build = () =>
|
||||
FundWalletUtil.createFundedDLCWallet(nodeApi,
|
||||
chainQueryApi,
|
||||
bip39PasswordOpt),
|
||||
destroy = { funded: FundedDLCWallet =>
|
||||
for {
|
||||
_ <- destroyDLCWallet(funded.wallet)
|
||||
} yield ()
|
||||
}
|
||||
)(test)
|
||||
}
|
||||
|
||||
/** Fixture for an initialized wallet which produce legacy addresses */
|
||||
def withLegacyWallet(test: OneArgAsyncTest): FutureOutcome = {
|
||||
withNewConfiguredWallet(legacyWalletConf)(test)
|
||||
@ -664,6 +688,14 @@ object BitcoinSWalletTest extends WalletLogger {
|
||||
} yield ()
|
||||
}
|
||||
|
||||
def destroyDLCWallet(wallet: DLCWallet): Future[Unit] = {
|
||||
import wallet.ec
|
||||
for {
|
||||
_ <- destroyWallet(wallet)
|
||||
_ <- wallet.dlcConfig.stop()
|
||||
} yield ()
|
||||
}
|
||||
|
||||
def destroyWalletAppConfig(walletAppConfig: WalletAppConfig): Future[Unit] = {
|
||||
val stoppedF = walletAppConfig.stop()
|
||||
stoppedF
|
||||
|
Loading…
Reference in New Issue
Block a user