Multi wallet support for DLC database (#3289)

* Multi wallet support for DLC database

* Fix for postgres
This commit is contained in:
benthecarman 2021-06-22 12:56:26 -05:00 committed by GitHub
parent 5f5f1b2b1a
commit cfe0c2f0d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 160 additions and 16 deletions

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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,

View File

@ -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()

View File

@ -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)

View File

@ -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