Add DLC callback for refunded DLC (#3989)

This commit is contained in:
rorp 2022-01-18 10:29:19 -08:00 committed by GitHub
parent 21c97bba12
commit 8a881b37f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 99 additions and 6 deletions

View File

@ -30,7 +30,6 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
val signedP: Promise[DLCStatus] = Promise()
val broadcastP: Promise[DLCStatus] = Promise()
//not implemented yet
val confirmedP: Promise[DLCStatus] = Promise()
val claimedP: Promise[DLCStatus] = Promise()
@ -49,8 +48,8 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
case DLCState.Broadcasted =>
//ignore broadcast from this wallet
Future.unit
case x @ (DLCState.Accepted | DLCState.Confirmed |
DLCState.RemoteClaimed | DLCState.Refunded) =>
case x @ (DLCState.Accepted | DLCState.RemoteClaimed |
DLCState.Refunded) =>
sys.error(s"Shouldn't receive state=$x for callback")
}
@ -85,7 +84,7 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
val initF = DLCWalletUtil.initDLC(wallets._1,
wallets._2,
DLCWalletUtil.sampleContractInfo)
val executeF = for {
def executeF = for {
_ <- initF
contractId <- DLCWalletUtil.getContractId(wallets._1.wallet)
fundingTx <- walletA.getDLCFundingTx(contractId)
@ -111,8 +110,8 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
accept <- acceptP.future
sign <- signedP.future
broadcast <- broadcastP.future
confirmed <- confirmedP.future
_ <- executeF
confirmed <- confirmedP.future
claimed <- claimedP.future
remoteClaimed <- remoteClaimedP.future
} yield {
@ -125,4 +124,87 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
assert(remoteClaimed.state == DLCState.RemoteClaimed)
}
}
it must "verify refunded callback is executed" in { wallets =>
val walletA: DLCWallet = wallets._1.wallet
val walletB: DLCWallet = wallets._2.wallet
val offerP: Promise[DLCStatus] = Promise()
val acceptP: Promise[DLCStatus] = Promise()
val signedP: Promise[DLCStatus] = Promise()
val broadcastP: Promise[DLCStatus] = Promise()
val refundedP: Promise[DLCStatus] = Promise()
val walletACallback: OnDLCStateChange = { case status: DLCStatus =>
status.state match {
case DLCState.Offered =>
Future.successful(offerP.success(status))
case DLCState.Signed =>
Future.successful(signedP.success(status))
case DLCState.Broadcasted | DLCState.Confirmed =>
//ignore them from this wallet
Future.unit
case DLCState.Refunded =>
Future.successful(refundedP.success(status))
case x @ (DLCState.Claimed | DLCState.Accepted |
DLCState.RemoteClaimed | DLCState.Refunded) =>
sys.error(s"Shouldn't receive state=$x for callback")
}
}
val walletBCallback: OnDLCStateChange = { case status: DLCStatus =>
status.state match {
case DLCState.Accepted =>
Future.successful(acceptP.success(status))
case DLCState.Broadcasted =>
Future.successful(broadcastP.success(status))
case x @ (DLCState.Refunded | DLCState.Offered | DLCState.Signed) =>
sys.error(s"Shouldn't receive state=$x for callback")
case DLCState.Confirmed | DLCState.Claimed | DLCState.RemoteClaimed =>
//do nothing, we are doing assertions for these on walletACallback
Future.unit
}
}
val walletACallbacks = DLCWalletCallbacks.onDLCStateChange(walletACallback)
val walletBCallbacks = DLCWalletCallbacks.onDLCStateChange(walletBCallback)
walletA.dlcConfig.addCallbacks(walletACallbacks)
walletB.dlcConfig.addCallbacks(walletBCallbacks)
//run init DLC and make sure we get the callback hit
val initF = DLCWalletUtil.initDLC(wallets._1,
wallets._2,
DLCWalletUtil.sampleContractInfo)
def refundF = for {
_ <- initF
contractId <- DLCWalletUtil.getContractId(wallets._1.wallet)
fundingTx <- walletA.getDLCFundingTx(contractId)
_ <- walletA.processTransaction(
transaction = fundingTx,
blockHashOpt = Some(CryptoGenerators.doubleSha256DigestBE.sample.get))
transaction <- walletA.executeDLCRefund(contractId)
_ <- walletB.processTransaction(transaction, None)
} yield ()
for {
_ <- initF
offer <- offerP.future
accept <- acceptP.future
sign <- signedP.future
broadcast <- broadcastP.future
_ <- refundF
refunded <- refundedP.future
} yield {
assert(offer.state == DLCState.Offered)
assert(accept.state == DLCState.Accepted)
assert(sign.state == DLCState.Signed)
assert(broadcast.state == DLCState.Broadcasted)
assert(refunded.state == DLCState.Refunded)
}
}
}

View File

@ -1413,6 +1413,9 @@ abstract class DLCWallet
for {
dlcDbOpt <- dlcDAO.findByContractId(contractId)
dlcDb = dlcDbOpt.get
offerDbOpt <- dlcOfferDAO.findByDLCId(dlcDb.dlcId)
_ = require(offerDbOpt.nonEmpty,
s"Invalid DLC $dlcDb.dlcId: no offer data")
contractData <- contractDataDAO.read(dlcDb.dlcId).map(_.get)
currentHeight <- chainQueryApi.getBestHashBlockHeight()
@ -1446,9 +1449,17 @@ abstract class DLCWallet
s"Created DLC refund transaction ${refundTx.txIdBE.hex} for contract ${contractId.toHex}")
_ <- updateDLCState(contractId, DLCState.Refunded)
_ <- updateClosingTxId(contractId, refundTx.txIdBE)
updatedDlcDb <- updateClosingTxId(contractId, refundTx.txIdBE)
_ <- processTransaction(refundTx, blockHashOpt = None)
closingTxOpt <- getClosingTxOpt(updatedDlcDb)
dlcAcceptOpt <- dlcAcceptDAO.findByDLCId(updatedDlcDb.dlcId)
status <- buildDLCStatus(updatedDlcDb,
contractData,
offerDbOpt.get,
dlcAcceptOpt,
closingTxOpt)
_ <- dlcConfig.walletCallbacks.executeOnDLCStateChange(logger, status.get)
} yield refundTx
}