mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-26 21:42:48 +01:00
2022 10 05 Delete legacy DLCSerializationVersion.Alpha
DLCs for a cleaner upgrade to v0 spec (#4817)
* Delete alpha DLCs * Get alpha migration working
This commit is contained in:
parent
c075112db5
commit
62081a43ec
4 changed files with 61 additions and 87 deletions
|
@ -5,6 +5,7 @@ import org.bitcoins.core.api.wallet.db.TransactionDbHelper
|
|||
import org.bitcoins.core.currency.Satoshis
|
||||
import org.bitcoins.core.number.{UInt32, UInt64}
|
||||
import org.bitcoins.core.protocol.script.EmptyScriptPubKey
|
||||
import org.bitcoins.core.protocol.tlv.DLCSerializationVersion
|
||||
import org.bitcoins.core.protocol.transaction.{
|
||||
TransactionConstants,
|
||||
TransactionOutPoint,
|
||||
|
@ -261,4 +262,16 @@ class DLCDAOTest extends BitcoinSWalletTest with DLCDAOFixture {
|
|||
assert(deleted.get.peerOpt.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
it must "read an alpha version of a DLC from the database" in { daos =>
|
||||
val alphaDLCDb =
|
||||
dlcDb.copy(serializationVersion = DLCSerializationVersion.Alpha)
|
||||
for {
|
||||
_ <- daos.dlcDAO.create(alphaDLCDb)
|
||||
foundOpt <- daos.dlcDAO.findByDLCSerializationVersion(
|
||||
DLCSerializationVersion.Alpha)
|
||||
} yield {
|
||||
assert(foundOpt.nonEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,23 +4,20 @@ import akka.actor.ActorSystem
|
|||
import com.typesafe.config.Config
|
||||
import org.bitcoins.commons.config.{AppConfigFactoryBase, ConfigOps}
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi
|
||||
import org.bitcoins.core.api.dlc.wallet.db.DLCDb
|
||||
import org.bitcoins.core.api.feeprovider.FeeRateApi
|
||||
import org.bitcoins.core.api.node.NodeApi
|
||||
import org.bitcoins.core.protocol.dlc.compute.DLCUtil
|
||||
import org.bitcoins.core.protocol.dlc.models.DLCState
|
||||
import org.bitcoins.core.protocol.dlc.models.DLCState.{
|
||||
AdaptorSigComputationState,
|
||||
ClosedState
|
||||
}
|
||||
import org.bitcoins.core.protocol.tlv.DLCSerializationVersion
|
||||
import org.bitcoins.core.util.Mutable
|
||||
import org.bitcoins.db.DatabaseDriver._
|
||||
import org.bitcoins.db._
|
||||
import org.bitcoins.dlc.wallet.internal.DLCDataManagement
|
||||
import org.bitcoins.dlc.wallet.models.{
|
||||
DLCSetupDbState,
|
||||
OfferedDbState,
|
||||
SetupCompleteDLCDbState
|
||||
}
|
||||
import org.bitcoins.keymanager.config.KeyManagerAppConfig
|
||||
import org.bitcoins.wallet.config.WalletAppConfig
|
||||
import org.bitcoins.wallet.models.TransactionDAO
|
||||
import org.bitcoins.wallet.{Wallet, WalletLogger}
|
||||
|
||||
import java.nio.file._
|
||||
|
@ -63,17 +60,18 @@ case class DLCAppConfig(
|
|||
migrate()
|
||||
}
|
||||
|
||||
val f = if (initMigrations != 0 && initMigrations <= 5) {
|
||||
val f = if (initMigrations != 0 && initMigrations <= 9) {
|
||||
//means we have an old wallet that we need to migrate
|
||||
logger.info(s"Running serialization version migration code")
|
||||
serializationVersionMigration()
|
||||
logger.info(s"Deleting alpha version DLCs")
|
||||
deleteAlphaVersionDLCs()
|
||||
} else {
|
||||
//the wallet is new enough where we cannot have any old
|
||||
//DLCs in the database with a broken contractId
|
||||
Future.unit
|
||||
}
|
||||
|
||||
logger.info(s"Applied $numMigrations to the dlc project")
|
||||
logger.info(
|
||||
s"Applied ${numMigrations.migrationsExecuted} to the dlc project. Started with initMigrations=$initMigrations")
|
||||
|
||||
f
|
||||
}
|
||||
|
@ -127,84 +125,29 @@ case class DLCAppConfig(
|
|||
callbacks.atomicUpdate(newCallbacks)(_ + _)
|
||||
}
|
||||
|
||||
/** Correctly populates the serialization version for existing DLCs
|
||||
* in our wallet database
|
||||
*/
|
||||
private def serializationVersionMigration(): Future[Unit] = {
|
||||
/** Delete alpha version DLCs, these are old protocol format DLCs that cannot be safely updated to the new protocol version of DLCs */
|
||||
private def deleteAlphaVersionDLCs(): Future[Unit] = {
|
||||
val dlcManagement = DLCDataManagement.fromDbAppConfig()(this, ec)
|
||||
val dlcDAO = dlcManagement.dlcDAO
|
||||
//read all existing DLCs
|
||||
val allDlcsF = dlcDAO.findAll()
|
||||
|
||||
//ugh, this is kinda nasty, idk how to make better though
|
||||
val walletAppConfig =
|
||||
WalletAppConfig(baseDatadir, configOverrides)
|
||||
val txDAO: TransactionDAO =
|
||||
TransactionDAO()(ec = ec, appConfig = walletAppConfig)
|
||||
//get the offers so we can figure out what the serialization version is
|
||||
val dlcDbContractInfoOfferF: Future[Vector[DLCSetupDbState]] = {
|
||||
for {
|
||||
allDlcs <- allDlcsF
|
||||
//only DLC with the alpha version need to be migrated
|
||||
alphaVersionDLCs = allDlcs.filter(
|
||||
_.serializationVersion == DLCSerializationVersion.Alpha)
|
||||
nestedOfferAndAccept = alphaVersionDLCs.map { a =>
|
||||
val setupDbOptF =
|
||||
dlcManagement.getDLCFundingData(a.dlcId, txDAO = txDAO)
|
||||
|
||||
setupDbOptF.foreach {
|
||||
case Some(_) => //happy path, do nothing
|
||||
case None =>
|
||||
logger.warn(s"Corrupted dlcId=${a.dlcId.hex} state=${a.state}, " +
|
||||
s"this is likely because of issue 4001 https://github.com/bitcoin-s/bitcoin-s/issues/4001 . " +
|
||||
s"This DLC will not have its contractId migrated to DLSerializationVersion.Beta")
|
||||
}
|
||||
setupDbOptF
|
||||
val alphaDLCsF =
|
||||
dlcDAO
|
||||
.findAll()
|
||||
.map(_.filter(_.serializationVersion == DLCSerializationVersion.Alpha))
|
||||
for {
|
||||
alphaDLCs <- alphaDLCsF
|
||||
_ <- Future.traverse(alphaDLCs) { dlc =>
|
||||
dlc.state match {
|
||||
case _: ClosedState | DLCState.Offered | DLCState.Accepted |
|
||||
_: AdaptorSigComputationState | DLCState.Signed =>
|
||||
logger.info(
|
||||
s"Deleting alpha version of a dlcId=${dlc.dlcId.hex} dlc=$dlc")
|
||||
dlcManagement.deleteByDLCId(dlc.dlcId)
|
||||
case DLCState.Broadcasted | DLCState.Confirmed =>
|
||||
sys.error(
|
||||
s"Cannot upgrade our DLC wallet as we have DLCs in progress using an ancient format of DLCs, dlcId=${dlc.dlcId.hex}")
|
||||
}
|
||||
offerAndAccepts <- Future.sequence(nestedOfferAndAccept)
|
||||
} yield {
|
||||
offerAndAccepts.flatten
|
||||
}
|
||||
}
|
||||
|
||||
//now we need to insert the serialization type
|
||||
//into global_dlc_data
|
||||
val updatedDLCDbsF = for {
|
||||
dlcDbContractInfoOffer <- dlcDbContractInfoOfferF
|
||||
} yield setSerializationVersions(dlcDbContractInfoOffer)
|
||||
|
||||
val updatedInDbF = updatedDLCDbsF.flatMap(dlcDAO.updateAll)
|
||||
|
||||
updatedInDbF.map(_ => ())
|
||||
}
|
||||
|
||||
/** Sets serialization versions on [[DLCDb]] based on the corresponding [[ContractInfo]] */
|
||||
private def setSerializationVersions(
|
||||
vec: Vector[DLCSetupDbState]): Vector[DLCDb] = {
|
||||
vec.map { case state: DLCSetupDbState =>
|
||||
val updatedDlcDb: DLCDb = state match {
|
||||
case acceptDbState: SetupCompleteDLCDbState =>
|
||||
val offer = acceptDbState.offer
|
||||
val acceptWithoutSigs = acceptDbState.acceptWithoutSigs
|
||||
val dlcDb = acceptDbState.dlcDb
|
||||
val contractId = DLCUtil.calcContractId(offer, acceptWithoutSigs)
|
||||
logger.info(
|
||||
s"Updating contractId for dlcId=${dlcDb.dlcId.hex} old contractId=${dlcDb.contractIdOpt
|
||||
.map(_.toHex)} new contractId=${contractId.toHex}")
|
||||
dlcDb.copy(tempContractId = offer.tempContractId,
|
||||
contractIdOpt = Some(contractId),
|
||||
serializationVersion = DLCSerializationVersion.Beta)
|
||||
case offerDbState: OfferedDbState =>
|
||||
//if we don't have an accept message, we can only calculate tempContractId
|
||||
val dlcDb = offerDbState.dlcDb
|
||||
val offer = offerDbState.offer
|
||||
logger.info(
|
||||
s"Updating tempContractId for dlcId=${dlcDb.dlcId.hex} old tempContractId=${dlcDb.tempContractId.hex} new contractId=${offer.tempContractId.hex}")
|
||||
dlcDb.copy(tempContractId = offer.tempContractId,
|
||||
serializationVersion = DLCSerializationVersion.Beta)
|
||||
}
|
||||
updatedDlcDb
|
||||
}
|
||||
} yield ()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -775,6 +775,11 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
|||
safeDatabase.run(action)
|
||||
}
|
||||
|
||||
def deleteByDLCId(dlcId: Sha256Digest): Future[Unit] = {
|
||||
val action = actionBuilder.deleteDLCAction(dlcId)
|
||||
safeDatabase.run(action)
|
||||
}
|
||||
|
||||
/** Retrieves the transaction(s) used to fund the offer message */
|
||||
private def getOfferPrevTxs(
|
||||
dlcDb: DLCDb,
|
||||
|
|
|
@ -173,7 +173,12 @@ case class DLCDAO()(implicit
|
|||
safeDatabase.run(action).map(_ => ())
|
||||
}
|
||||
|
||||
private def updatePeerAction(dlcId: Sha256Digest, peerOpt: Option[String]) = {
|
||||
private def updatePeerAction(
|
||||
dlcId: Sha256Digest,
|
||||
peerOpt: Option[String]): DBIOAction[
|
||||
Int,
|
||||
NoStream,
|
||||
Effect.Read with Effect.Write] = {
|
||||
val dlcQuery = table.filter(_.dlcId === dlcId)
|
||||
|
||||
for {
|
||||
|
@ -186,6 +191,14 @@ case class DLCDAO()(implicit
|
|||
} yield res
|
||||
}
|
||||
|
||||
def findByDLCSerializationVersion(
|
||||
version: DLCSerializationVersion): Future[Vector[DLCDb]] = {
|
||||
val action = table.filter(_.serializationVersion === version).result
|
||||
safeDatabase
|
||||
.run(action)
|
||||
.map(_.toVector)
|
||||
}
|
||||
|
||||
class DLCTable(tag: Tag)
|
||||
extends Table[DLCDb](tag, schemaName, "global_dlc_data") {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue