mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-26 21:42:48 +01:00
2022 01 31 issue 4030 (#4066)
* WIP * WIP * Get basic unit test passing for new adaptor sig states * Fix compile
This commit is contained in:
parent
f253b5055e
commit
9de4b0272a
11 changed files with 267 additions and 44 deletions
|
@ -819,6 +819,28 @@ object Picklers {
|
|||
)
|
||||
}
|
||||
|
||||
implicit val acceptedComputingAdaptorSigsW: Writer[
|
||||
AcceptedComputingAdaptorSigs] = writer[Obj].comap { accepted =>
|
||||
import accepted._
|
||||
Obj(
|
||||
"state" -> Str(statusString),
|
||||
"dlcId" -> Str(dlcId.hex),
|
||||
"isInitiator" -> Bool(isInitiator),
|
||||
"lastUpdated" -> Str(iso8601ToString(lastUpdated)),
|
||||
"tempContractId" -> Str(tempContractId.hex),
|
||||
"contractId" -> Str(contractId.toHex),
|
||||
"contractInfo" -> Str(contractInfo.hex),
|
||||
"contractMaturity" -> Num(
|
||||
timeouts.contractMaturity.toUInt32.toLong.toDouble),
|
||||
"contractTimeout" -> Num(
|
||||
timeouts.contractTimeout.toUInt32.toLong.toDouble),
|
||||
"feeRate" -> Num(feeRate.toLong.toDouble),
|
||||
"totalCollateral" -> Num(totalCollateral.satoshis.toLong.toDouble),
|
||||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble)
|
||||
)
|
||||
}
|
||||
|
||||
implicit val acceptedW: Writer[Accepted] = writer[Obj].comap { accepted =>
|
||||
import accepted._
|
||||
Obj(
|
||||
|
@ -840,6 +862,29 @@ object Picklers {
|
|||
)
|
||||
}
|
||||
|
||||
implicit val signedComputingAdaptorSigsW: Writer[SignedComputingAdaptorSigs] =
|
||||
writer[Obj].comap { signed =>
|
||||
import signed._
|
||||
Obj(
|
||||
"state" -> Str(statusString),
|
||||
"dlcId" -> Str(dlcId.hex),
|
||||
"isInitiator" -> Bool(isInitiator),
|
||||
"lastUpdated" -> Str(iso8601ToString(lastUpdated)),
|
||||
"tempContractId" -> Str(tempContractId.hex),
|
||||
"contractId" -> Str(contractId.toHex),
|
||||
"contractInfo" -> Str(contractInfo.hex),
|
||||
"contractMaturity" -> Num(
|
||||
timeouts.contractMaturity.toUInt32.toLong.toDouble),
|
||||
"contractTimeout" -> Num(
|
||||
timeouts.contractTimeout.toUInt32.toLong.toDouble),
|
||||
"feeRate" -> Num(feeRate.toLong.toDouble),
|
||||
"totalCollateral" -> Num(totalCollateral.satoshis.toLong.toDouble),
|
||||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"fundingTxId" -> Str(fundingTxId.hex)
|
||||
)
|
||||
}
|
||||
|
||||
implicit val signedW: Writer[Signed] = writer[Obj].comap { signed =>
|
||||
import signed._
|
||||
Obj(
|
||||
|
@ -1023,8 +1068,12 @@ object Picklers {
|
|||
implicit val dlcStatusW: Writer[DLCStatus] = writer[Value].comap {
|
||||
case o: Offered =>
|
||||
writeJs(o)(offeredW)
|
||||
case a: AcceptedComputingAdaptorSigs =>
|
||||
writeJs(a)(acceptedComputingAdaptorSigsW)
|
||||
case a: Accepted =>
|
||||
writeJs(a)(acceptedW)
|
||||
case s: SignedComputingAdaptorSigs =>
|
||||
writeJs(s)(signedComputingAdaptorSigsW)
|
||||
case s: Signed =>
|
||||
writeJs(s)(signedW)
|
||||
case b: Broadcasted =>
|
||||
|
@ -1110,6 +1159,19 @@ object Picklers {
|
|||
totalCollateral,
|
||||
localCollateral
|
||||
)
|
||||
case DLCState.AcceptComputingAdaptorSigs =>
|
||||
AcceptedComputingAdaptorSigs(
|
||||
dlcId,
|
||||
isInitiator,
|
||||
lastUpdated,
|
||||
tempContractId,
|
||||
contractId,
|
||||
ContractInfo.fromTLV(contractInfoTLV),
|
||||
DLCTimeouts(contractMaturity, contractTimeout),
|
||||
feeRate,
|
||||
totalCollateral,
|
||||
localCollateral
|
||||
)
|
||||
case DLCState.Accepted =>
|
||||
Accepted(
|
||||
dlcId,
|
||||
|
@ -1123,6 +1185,20 @@ object Picklers {
|
|||
totalCollateral,
|
||||
localCollateral
|
||||
)
|
||||
case DLCState.SignComputingAdaptorSigs =>
|
||||
SignedComputingAdaptorSigs(
|
||||
dlcId,
|
||||
isInitiator,
|
||||
lastUpdated,
|
||||
tempContractId,
|
||||
contractId,
|
||||
ContractInfo.fromTLV(contractInfoTLV),
|
||||
DLCTimeouts(contractMaturity, contractTimeout),
|
||||
feeRate,
|
||||
totalCollateral,
|
||||
localCollateral,
|
||||
fundingTxId
|
||||
)
|
||||
case DLCState.Signed =>
|
||||
Signed(
|
||||
dlcId,
|
||||
|
|
|
@ -245,7 +245,9 @@ class DLCPaneModel(pane: DLCPane)(implicit ec: ExecutionContext)
|
|||
val eventId = status.eventIds.head
|
||||
|
||||
val confirmed = status.state match {
|
||||
case DLCState.Offered | DLCState.Accepted =>
|
||||
case DLCState.Offered | DLCState.Accepted |
|
||||
DLCState.AcceptComputingAdaptorSigs |
|
||||
DLCState.SignComputingAdaptorSigs =>
|
||||
new Alert(AlertType.Confirmation) {
|
||||
initOwner(owner)
|
||||
headerText = "Confirm Canceling DLC"
|
||||
|
|
|
@ -218,7 +218,9 @@ class DLCTableView(model: DLCPaneModel) {
|
|||
row.item.onChange { (_, _, newContent) =>
|
||||
if (newContent != null) {
|
||||
cancelDLCItem.disable = row.item.value.state match {
|
||||
case DLCState.Offered | DLCState.Accepted | DLCState.Signed =>
|
||||
case DLCState.Offered | DLCState.Accepted | DLCState.Signed |
|
||||
DLCState.AcceptComputingAdaptorSigs |
|
||||
DLCState.SignComputingAdaptorSigs =>
|
||||
false
|
||||
case DLCState.Confirmed | DLCState.Broadcasted |
|
||||
DLCState.Claimed | DLCState.Refunded |
|
||||
|
@ -230,7 +232,9 @@ class DLCTableView(model: DLCPaneModel) {
|
|||
false
|
||||
case DLCState.Offered | DLCState.Accepted | DLCState.Signed |
|
||||
DLCState.Claimed | DLCState.Refunded |
|
||||
DLCState.RemoteClaimed =>
|
||||
DLCState.RemoteClaimed |
|
||||
DLCState.AcceptComputingAdaptorSigs |
|
||||
DLCState.SignComputingAdaptorSigs =>
|
||||
true
|
||||
}
|
||||
refundDLCItem.disable = disableRefundExecute
|
||||
|
|
|
@ -13,6 +13,12 @@ object DLCState extends StringFactory[DLCState] {
|
|||
/** Means that someone has attempted to claim the DLC */
|
||||
sealed abstract class ClosedState extends DLCState
|
||||
|
||||
/** A state meant to represent we are computing adaptor sigs.
|
||||
* Computing adaptor signatures can take awhile on certain hardware
|
||||
* (raspberry pi) which is why we model this state
|
||||
*/
|
||||
sealed abstract class AdaptorSigComputationState extends InProgressState
|
||||
|
||||
/** A state that requires an oracle outcome to be valid */
|
||||
sealed trait ClosedViaOracleOutcomeState extends ClosedState
|
||||
|
||||
|
@ -20,14 +26,22 @@ object DLCState extends StringFactory[DLCState] {
|
|||
* accept message has yet been created/received.
|
||||
*/
|
||||
final case object Offered extends InProgressState {
|
||||
val order: Int = 0
|
||||
override val order: Int = 0
|
||||
}
|
||||
|
||||
case object AcceptComputingAdaptorSigs extends AdaptorSigComputationState {
|
||||
override val order: Int = 1
|
||||
}
|
||||
|
||||
/** The state where an offer has been accepted but
|
||||
* no sign message has yet been created/received.
|
||||
*/
|
||||
final case object Accepted extends InProgressState {
|
||||
val order: Int = 1
|
||||
override val order: Int = 2
|
||||
}
|
||||
|
||||
case object SignComputingAdaptorSigs extends AdaptorSigComputationState {
|
||||
override val order: Int = 3
|
||||
}
|
||||
|
||||
/** The state where the initiating party has created
|
||||
|
@ -36,7 +50,7 @@ object DLCState extends StringFactory[DLCState] {
|
|||
* broadcasted to the network.
|
||||
*/
|
||||
final case object Signed extends InProgressState {
|
||||
val order: Int = 2
|
||||
override val order: Int = 4
|
||||
}
|
||||
|
||||
/** The state where the accepting (non-initiating)
|
||||
|
@ -44,7 +58,7 @@ object DLCState extends StringFactory[DLCState] {
|
|||
* to the blockchain, and it has not yet been confirmed.
|
||||
*/
|
||||
final case object Broadcasted extends InProgressState {
|
||||
val order: Int = 3
|
||||
override val order: Int = 5
|
||||
}
|
||||
|
||||
/** The state where the DLC funding transaction has been
|
||||
|
@ -52,32 +66,34 @@ object DLCState extends StringFactory[DLCState] {
|
|||
* initiated.
|
||||
*/
|
||||
final case object Confirmed extends InProgressState {
|
||||
val order: Int = 4
|
||||
override val order: Int = 6
|
||||
}
|
||||
|
||||
/** The state where one of the CETs has been accepted by the network
|
||||
* and executed by ourselves.
|
||||
*/
|
||||
final case object Claimed extends ClosedViaOracleOutcomeState {
|
||||
val order: Int = 4
|
||||
override val order: Int = 7
|
||||
}
|
||||
|
||||
/** The state where one of the CETs has been accepted by the network
|
||||
* and executed by a remote party.
|
||||
*/
|
||||
final case object RemoteClaimed extends ClosedViaOracleOutcomeState {
|
||||
val order: Int = 5
|
||||
override val order: Int = 7
|
||||
}
|
||||
|
||||
/** The state where the DLC refund transaction has been
|
||||
* accepted by the network.
|
||||
*/
|
||||
final case object Refunded extends ClosedState {
|
||||
val order: Int = 6
|
||||
val order: Int = 7
|
||||
}
|
||||
|
||||
val all: Vector[DLCState] = Vector(Offered,
|
||||
AcceptComputingAdaptorSigs,
|
||||
Accepted,
|
||||
SignComputingAdaptorSigs,
|
||||
Signed,
|
||||
Broadcasted,
|
||||
Confirmed,
|
||||
|
@ -85,7 +101,7 @@ object DLCState extends StringFactory[DLCState] {
|
|||
RemoteClaimed,
|
||||
Refunded)
|
||||
|
||||
def fromString(str: String): DLCState = {
|
||||
override def fromString(str: String): DLCState = {
|
||||
all.find(state => str.toLowerCase() == state.toString.toLowerCase) match {
|
||||
case Some(state) => state
|
||||
case None =>
|
||||
|
|
|
@ -92,6 +92,23 @@ object DLCStatus {
|
|||
override val state: DLCState.Offered.type = DLCState.Offered
|
||||
}
|
||||
|
||||
case class AcceptedComputingAdaptorSigs(
|
||||
dlcId: Sha256Digest,
|
||||
isInitiator: Boolean,
|
||||
lastUpdated: Instant,
|
||||
tempContractId: Sha256Digest,
|
||||
contractId: ByteVector,
|
||||
contractInfo: ContractInfo,
|
||||
timeouts: DLCTimeouts,
|
||||
feeRate: FeeUnit,
|
||||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit)
|
||||
extends AcceptedDLCStatus {
|
||||
|
||||
override val state: DLCState.AcceptComputingAdaptorSigs.type =
|
||||
DLCState.AcceptComputingAdaptorSigs
|
||||
}
|
||||
|
||||
case class Accepted(
|
||||
dlcId: Sha256Digest,
|
||||
isInitiator: Boolean,
|
||||
|
@ -107,6 +124,24 @@ object DLCStatus {
|
|||
override val state: DLCState.Accepted.type = DLCState.Accepted
|
||||
}
|
||||
|
||||
case class SignedComputingAdaptorSigs(
|
||||
dlcId: Sha256Digest,
|
||||
isInitiator: Boolean,
|
||||
lastUpdated: Instant,
|
||||
tempContractId: Sha256Digest,
|
||||
contractId: ByteVector,
|
||||
contractInfo: ContractInfo,
|
||||
timeouts: DLCTimeouts,
|
||||
feeRate: FeeUnit,
|
||||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
fundingTxId: DoubleSha256DigestBE)
|
||||
extends SignedDLCStatus {
|
||||
|
||||
override val state: DLCState.SignComputingAdaptorSigs.type =
|
||||
DLCState.SignComputingAdaptorSigs
|
||||
}
|
||||
|
||||
case class Signed(
|
||||
dlcId: Sha256Digest,
|
||||
isInitiator: Boolean,
|
||||
|
@ -230,7 +265,8 @@ object DLCStatus {
|
|||
status match {
|
||||
case status: SignedDLCStatus =>
|
||||
Some(status.fundingTxId)
|
||||
case _: Offered | _: Accepted | _: Signed =>
|
||||
case _: Offered | _: Accepted | _: Signed |
|
||||
_: AcceptedComputingAdaptorSigs =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +285,8 @@ object DLCStatus {
|
|||
status match {
|
||||
case claimed: ClaimedDLCStatus =>
|
||||
Some(claimed.oracleSigs)
|
||||
case _: Offered | _: Accepted | _: SignedDLCStatus | _: Refunded =>
|
||||
case _: Offered | _: Accepted | _: AcceptedComputingAdaptorSigs |
|
||||
_: SignedDLCStatus | _: Refunded =>
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
val walletA: DLCWallet = wallets._1.wallet
|
||||
val walletB: DLCWallet = wallets._2.wallet
|
||||
val offerP: Promise[DLCStatus] = Promise()
|
||||
val acceptedSignComputingAdaptorSigsP: Promise[DLCStatus] = Promise()
|
||||
val acceptP: Promise[DLCStatus] = Promise()
|
||||
val signedComputingAdaptorSigsP: Promise[DLCStatus] = Promise()
|
||||
val signedP: Promise[DLCStatus] = Promise()
|
||||
val broadcastP: Promise[DLCStatus] = Promise()
|
||||
|
||||
|
@ -39,6 +41,8 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
status.state match {
|
||||
case DLCState.Offered =>
|
||||
Future.successful(offerP.success(status))
|
||||
case DLCState.SignComputingAdaptorSigs =>
|
||||
Future.successful(signedComputingAdaptorSigsP.success(status))
|
||||
case DLCState.Signed =>
|
||||
Future.successful(signedP.success(status))
|
||||
case DLCState.Confirmed =>
|
||||
|
@ -48,8 +52,8 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
case DLCState.Broadcasted =>
|
||||
//ignore broadcast from this wallet
|
||||
Future.unit
|
||||
case x @ (DLCState.Accepted | DLCState.RemoteClaimed |
|
||||
DLCState.Refunded) =>
|
||||
case x @ (DLCState.Accepted | DLCState.AcceptComputingAdaptorSigs |
|
||||
DLCState.RemoteClaimed | DLCState.Refunded) =>
|
||||
sys.error(s"Shouldn't receive state=$x for callback")
|
||||
}
|
||||
|
||||
|
@ -57,19 +61,21 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
|
||||
val walletBCallback: OnDLCStateChange = { case status: DLCStatus =>
|
||||
status.state match {
|
||||
case DLCState.AcceptComputingAdaptorSigs =>
|
||||
Future.successful(acceptedSignComputingAdaptorSigsP.success(status))
|
||||
case DLCState.Accepted =>
|
||||
Future.successful(acceptP.success(status))
|
||||
case DLCState.Broadcasted =>
|
||||
Future.successful(broadcastP.success(status))
|
||||
case DLCState.RemoteClaimed =>
|
||||
Future.successful(remoteClaimedP.success(status))
|
||||
case x @ (DLCState.Offered | DLCState.Signed) =>
|
||||
case x @ (DLCState.Offered | DLCState.Signed |
|
||||
DLCState.SignComputingAdaptorSigs) =>
|
||||
sys.error(s"Shouldn't receive state=$x for callback")
|
||||
case DLCState.Confirmed | DLCState.Claimed | DLCState.Refunded =>
|
||||
//do nothing, we are doing assertions for these on walletACallback
|
||||
Future.unit
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val walletACallbacks = DLCWalletCallbacks.onDLCStateChange(walletACallback)
|
||||
|
@ -107,7 +113,9 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
for {
|
||||
_ <- initF
|
||||
offer <- offerP.future
|
||||
acceptedComputingAdaptorSigs <- acceptedSignComputingAdaptorSigsP.future
|
||||
accept <- acceptP.future
|
||||
signComputingAdaptorSigs <- signedComputingAdaptorSigsP.future
|
||||
sign <- signedP.future
|
||||
broadcast <- broadcastP.future
|
||||
_ <- executeF
|
||||
|
@ -116,7 +124,11 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
remoteClaimed <- remoteClaimedP.future
|
||||
} yield {
|
||||
assert(offer.state == DLCState.Offered)
|
||||
assert(
|
||||
acceptedComputingAdaptorSigs.state == DLCState.AcceptComputingAdaptorSigs)
|
||||
assert(accept.state == DLCState.Accepted)
|
||||
assert(
|
||||
signComputingAdaptorSigs.state == DLCState.SignComputingAdaptorSigs)
|
||||
assert(sign.state == DLCState.Signed)
|
||||
assert(broadcast.state == DLCState.Broadcasted)
|
||||
assert(confirmed.state == DLCState.Confirmed)
|
||||
|
@ -129,7 +141,9 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
val walletA: DLCWallet = wallets._1.wallet
|
||||
val walletB: DLCWallet = wallets._2.wallet
|
||||
val offerP: Promise[DLCStatus] = Promise()
|
||||
val acceptedComputingAdaptorSigsP: Promise[DLCStatus] = Promise()
|
||||
val acceptP: Promise[DLCStatus] = Promise()
|
||||
val signedComputingAdaptorSigsP: Promise[DLCStatus] = Promise()
|
||||
val signedP: Promise[DLCStatus] = Promise()
|
||||
val broadcastP: Promise[DLCStatus] = Promise()
|
||||
val refundedP: Promise[DLCStatus] = Promise()
|
||||
|
@ -138,6 +152,8 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
status.state match {
|
||||
case DLCState.Offered =>
|
||||
Future.successful(offerP.success(status))
|
||||
case DLCState.SignComputingAdaptorSigs =>
|
||||
Future.successful(signedComputingAdaptorSigsP.success(status))
|
||||
case DLCState.Signed =>
|
||||
Future.successful(signedP.success(status))
|
||||
case DLCState.Broadcasted | DLCState.Confirmed =>
|
||||
|
@ -145,8 +161,8 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
Future.unit
|
||||
case DLCState.Refunded =>
|
||||
Future.successful(refundedP.success(status))
|
||||
case x @ (DLCState.Claimed | DLCState.Accepted |
|
||||
DLCState.RemoteClaimed | DLCState.Refunded) =>
|
||||
case x @ (DLCState.Claimed | DLCState.AcceptComputingAdaptorSigs |
|
||||
DLCState.Accepted | DLCState.RemoteClaimed | DLCState.Refunded) =>
|
||||
sys.error(s"Shouldn't receive state=$x for callback")
|
||||
}
|
||||
|
||||
|
@ -154,11 +170,14 @@ class DLCWalletCallbackTest extends BitcoinSDualWalletTest {
|
|||
|
||||
val walletBCallback: OnDLCStateChange = { case status: DLCStatus =>
|
||||
status.state match {
|
||||
case DLCState.AcceptComputingAdaptorSigs =>
|
||||
Future.successful(acceptedComputingAdaptorSigsP.success(status))
|
||||
case DLCState.Accepted =>
|
||||
Future.successful(acceptP.success(status))
|
||||
case DLCState.Broadcasted =>
|
||||
Future.successful(broadcastP.success(status))
|
||||
case x @ (DLCState.Refunded | DLCState.Offered | DLCState.Signed) =>
|
||||
case x @ (DLCState.Refunded | DLCState.Offered |
|
||||
DLCState.SignComputingAdaptorSigs | 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
|
||||
|
|
|
@ -435,19 +435,25 @@ abstract class DLCWallet
|
|||
/** Retrieves the [[DLCDb]] and [[AccountDb]] for the given tempContractId
|
||||
* else returns None
|
||||
*/
|
||||
private def getDlcDbOfferDb(
|
||||
tempContractId: Sha256Digest): Future[Option[(DLCDb, DLCOfferDb)]] = {
|
||||
val result: Future[Option[(DLCDb, DLCOfferDb)]] = for {
|
||||
private def getDlcDbOfferDbContractDataDb(
|
||||
tempContractId: Sha256Digest): Future[
|
||||
Option[(DLCDb, DLCOfferDb, DLCContractDataDb)]] = {
|
||||
val result: Future[Option[(DLCDb, DLCOfferDb, DLCContractDataDb)]] = for {
|
||||
dlcDbOpt <- dlcDAO.findByTempContractId(tempContractId)
|
||||
dlcOfferDbOpt <- dlcDbOpt match {
|
||||
case Some(dlcDb) => dlcOfferDAO.findByDLCId(dlcDb.dlcId)
|
||||
case None => Future.successful(None)
|
||||
}
|
||||
contractDataDbOpt <- dlcDbOpt match {
|
||||
case Some(dlcDb) => contractDataDAO.findByDLCId(dlcDb.dlcId)
|
||||
case None => Future.successful(None)
|
||||
}
|
||||
} yield {
|
||||
for {
|
||||
dlcDb <- dlcDbOpt
|
||||
dlcOfferDb <- dlcOfferDbOpt
|
||||
} yield (dlcDb, dlcOfferDb)
|
||||
contractDataDb <- contractDataDbOpt
|
||||
} yield (dlcDb, dlcOfferDb, contractDataDb)
|
||||
}
|
||||
|
||||
result
|
||||
|
@ -455,7 +461,7 @@ abstract class DLCWallet
|
|||
|
||||
private def initDLCForAccept(
|
||||
offer: DLCOffer,
|
||||
account: AccountDb): Future[(DLCDb, DLCOfferDb)] = {
|
||||
account: AccountDb): Future[(DLCDb, DLCOfferDb, DLCContractDataDb)] = {
|
||||
logger.info(
|
||||
s"Initializing DLC from received offer with tempContractId ${offer.tempContractId.hex}")
|
||||
val dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
@ -472,9 +478,9 @@ abstract class DLCWallet
|
|||
groupByExistingAnnouncements(announcements)
|
||||
}
|
||||
|
||||
getDlcDbOfferDb(offer.tempContractId).flatMap {
|
||||
case Some((dlcDb, dlcOffer)) =>
|
||||
Future.successful((dlcDb, dlcOffer))
|
||||
getDlcDbOfferDbContractDataDb(offer.tempContractId).flatMap {
|
||||
case Some((dlcDb, dlcOffer, contractDataDb)) =>
|
||||
Future.successful((dlcDb, dlcOffer, contractDataDb))
|
||||
case None =>
|
||||
for {
|
||||
nextIndex <- getNextAvailableIndex(account, chainType)
|
||||
|
@ -500,11 +506,12 @@ abstract class DLCWallet
|
|||
dlcDb <- dlcDbAction
|
||||
ann <- createdAnnouncementsAction
|
||||
//we don't need the contract data db, so don't return it
|
||||
_ <- contractAction
|
||||
contractDataDb <- contractAction
|
||||
offer <- dlcOfferAction
|
||||
} yield (dlcDb, ann, offer)
|
||||
} yield (dlcDb, ann, offer, contractDataDb)
|
||||
}
|
||||
(writtenDLC, createdDbs, offerDb) <- safeDatabase.run(zipped)
|
||||
(writtenDLC, createdDbs, offerDb, contractDataDb) <- safeDatabase.run(
|
||||
zipped)
|
||||
announcementDataDbs =
|
||||
createdDbs ++ groupedAnnouncements.existingAnnouncements
|
||||
|
||||
|
@ -534,7 +541,7 @@ abstract class DLCWallet
|
|||
|
||||
_ <- safeDatabase.run(
|
||||
DBIOAction.seq(createNonceAction, createAnnouncementAction))
|
||||
} yield (writtenDLC, offerDb)
|
||||
} yield (writtenDLC, offerDb, contractDataDb)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,16 +606,16 @@ abstract class DLCWallet
|
|||
|
||||
val accountF = getDefaultAccountForType(AddressType.SegWit)
|
||||
|
||||
val dlcDbOfferDbF: Future[(DLCDb, DLCOfferDb)] = {
|
||||
val dlcDbOfferDbF: Future[(DLCDb, DLCOfferDb, DLCContractDataDb)] = {
|
||||
for {
|
||||
accountDb <- accountF
|
||||
(dlcDb, offerDb) <- initDLCForAccept(offer, accountDb)
|
||||
} yield (dlcDb, offerDb)
|
||||
(dlcDb, offerDb, contractDataDb) <- initDLCForAccept(offer, accountDb)
|
||||
} yield (dlcDb, offerDb, contractDataDb)
|
||||
}
|
||||
|
||||
val fundingPrivKeyF: Future[AdaptorSign] = {
|
||||
for {
|
||||
(dlc, _) <- dlcDbOfferDbF
|
||||
(dlc, _, _) <- dlcDbOfferDbF
|
||||
account <- accountF
|
||||
bip32Path = BIP32Path(
|
||||
account.hdAccount.path ++ Vector(BIP32Node(0, hardened = false),
|
||||
|
@ -619,7 +626,7 @@ abstract class DLCWallet
|
|||
}
|
||||
|
||||
for {
|
||||
(dlc, _) <- dlcDbOfferDbF
|
||||
(dlc, offerDb, contractDataDb) <- dlcDbOfferDbF
|
||||
account <- accountF
|
||||
(txBuilder, spendingInfos) <- fundDLCAcceptMsg(offer = offer,
|
||||
collateral = collateral,
|
||||
|
@ -639,6 +646,8 @@ abstract class DLCWallet
|
|||
|
||||
contractId = builder.calcContractId
|
||||
|
||||
dlcDbWithContractId = dlc.copy(contractIdOpt = Some(contractId))
|
||||
|
||||
signer = DLCTxSigner(builder = builder,
|
||||
isInitiator = false,
|
||||
fundingKey = fundingPrivKey,
|
||||
|
@ -652,8 +661,14 @@ abstract class DLCWallet
|
|||
case Some(_) => Future.unit
|
||||
case None => scriptPubKeyDAO.create(spkDb)
|
||||
}
|
||||
|
||||
_ = logger.info(s"Creating CET Sigs for ${contractId.toHex}")
|
||||
//emit websocket event that we are now computing adaptor signatures
|
||||
status = DLCStatusBuilder.buildInProgressDLCStatus(
|
||||
dlcDb = dlcDbWithContractId,
|
||||
contractInfo = offer.contractInfo,
|
||||
contractData = contractDataDb,
|
||||
offerDb = offerDb)
|
||||
_ = dlcConfig.walletCallbacks.executeOnDLCStateChange(logger, status)
|
||||
cetSigs <- signer.createCETSigsAsync()
|
||||
refundSig = signer.signRefundTx
|
||||
_ = logger.debug(
|
||||
|
@ -726,11 +741,13 @@ abstract class DLCWallet
|
|||
|
||||
_ <- remoteTxDAO.upsertAll(offerPrevTxs)
|
||||
actions = actionBuilder.buildCreateAcceptAction(
|
||||
dlcDb = dlcDbWithContractId.updateState(DLCState.Accepted),
|
||||
dlcAcceptDb = dlcAcceptDb,
|
||||
offerInputs = offerInputs,
|
||||
acceptInputs = acceptInputs,
|
||||
cetSigsDb = sigsDbs,
|
||||
refundSigsDb = refundSigsDb)
|
||||
refundSigsDb = refundSigsDb
|
||||
)
|
||||
_ <- safeDatabase.run(actions)
|
||||
dlcDb <- updateDLCContractIds(offer, accept)
|
||||
_ = logger.info(
|
||||
|
@ -918,6 +935,7 @@ abstract class DLCWallet
|
|||
signerOpt match {
|
||||
case Some(signer) =>
|
||||
val cetSigsF = getCetSigs(signer = signer,
|
||||
dlcDb = dlc,
|
||||
contractId = contractId,
|
||||
cetSigsDbs = cetSigsDbs,
|
||||
mySigs = mySigs)
|
||||
|
@ -972,12 +990,20 @@ abstract class DLCWallet
|
|||
|
||||
private def getCetSigs(
|
||||
signer: DLCTxSigner,
|
||||
dlcDb: DLCDb,
|
||||
contractId: ByteVector,
|
||||
cetSigsDbs: Vector[DLCCETSignaturesDb],
|
||||
mySigs: Vector[DLCCETSignaturesDb]): Future[CETSignatures] = {
|
||||
if (mySigs.forall(_.initiatorSig.isEmpty)) {
|
||||
logger.info(s"Creating CET Sigs for contract ${contractId.toHex}")
|
||||
val dlcDbSignComputingAdaptorSigs =
|
||||
dlcDb.updateState(DLCState.SignComputingAdaptorSigs)
|
||||
val updatedF = dlcDAO.update(dlcDbSignComputingAdaptorSigs)
|
||||
for {
|
||||
_ <- updatedF
|
||||
status <- findDLC(dlcDb.dlcId)
|
||||
_ <- dlcConfig.walletCallbacks.executeOnDLCStateChange(logger,
|
||||
status.get)
|
||||
sigs <- signer.createCETSigsAsync()
|
||||
|
||||
sigsDbs: Vector[DLCCETSignaturesDb] = sigs.outcomeSigs
|
||||
|
@ -1145,6 +1171,10 @@ abstract class DLCWallet
|
|||
Future.failed(
|
||||
new RuntimeException(
|
||||
"Cannot add sigs to a DLC before it has been accepted"))
|
||||
case _: AdaptorSigComputationState =>
|
||||
val err = new RuntimeException(
|
||||
s"Cannot add sigs to a DLC while adaptor sigs are being computed, contractId=${sign.contractId.toHex}")
|
||||
Future.failed(err)
|
||||
case Accepted =>
|
||||
logger.info(
|
||||
s"Verifying CET Signatures for contract ${sign.contractId.toHex}")
|
||||
|
@ -1304,7 +1334,8 @@ abstract class DLCWallet
|
|||
dlcDb.state match {
|
||||
case DLCState.Broadcasted | DLCState.Signed => dlcDb
|
||||
case state @ (DLCState.Offered | DLCState.Confirmed | DLCState.Accepted |
|
||||
DLCState.Claimed | DLCState.RemoteClaimed | DLCState.Refunded) =>
|
||||
DLCState.Claimed | DLCState.RemoteClaimed | DLCState.Refunded |
|
||||
_: DLCState.AdaptorSigComputationState) =>
|
||||
sys.error(
|
||||
s"Cannot broadcast the dlc when it is in the state=${state} contractId=${dlcDb.contractIdOpt}")
|
||||
}
|
||||
|
|
|
@ -114,7 +114,8 @@ private[bitcoins] trait DLCTransactionProcessing extends TransactionProcessing {
|
|||
.deleteByDLCId(updated.dlcId)
|
||||
.map(_ => ())
|
||||
case DLCState.Offered | DLCState.Accepted | DLCState.Signed |
|
||||
DLCState.Broadcasted | DLCState.Confirmed =>
|
||||
DLCState.Broadcasted | DLCState.Confirmed |
|
||||
_: DLCState.AdaptorSigComputationState =>
|
||||
FutureUtil.unit
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +256,10 @@ private[bitcoins] trait DLCTransactionProcessing extends TransactionProcessing {
|
|||
if (blockHashOpt.isDefined)
|
||||
dlcDb.updateState(DLCState.Confirmed)
|
||||
else dlcDb.copy(state = DLCState.Broadcasted)
|
||||
case _: DLCState.AdaptorSigComputationState =>
|
||||
val contractIdOpt = dlcDb.contractIdOpt.map(_.toHex)
|
||||
throw new IllegalStateException(
|
||||
s"Cannot be settling a DLC when we are computing adaptor sigs! contractId=${contractIdOpt}")
|
||||
case DLCState.Confirmed | DLCState.Claimed |
|
||||
DLCState.RemoteClaimed | DLCState.Refunded =>
|
||||
dlcDb
|
||||
|
|
|
@ -108,7 +108,7 @@ object DLCAcceptUtil extends Logging {
|
|||
tempContractId = offer.tempContractId,
|
||||
contractIdOpt = None,
|
||||
protocolVersion = 0,
|
||||
state = DLCState.Accepted,
|
||||
state = DLCState.AcceptComputingAdaptorSigs,
|
||||
isInitiator = false,
|
||||
account = account.hdAccount,
|
||||
changeIndex = chainType,
|
||||
|
|
|
@ -55,6 +55,7 @@ case class DLCActionBuilder(dlcWalletDAOs: DLCWalletDAOs) {
|
|||
* offer table, accept table, cet sigs table, inputs table, and refund table
|
||||
*/
|
||||
def buildCreateAcceptAction(
|
||||
dlcDb: DLCDb,
|
||||
dlcAcceptDb: DLCAcceptDb,
|
||||
offerInputs: Vector[DLCFundingInputDb],
|
||||
acceptInputs: Vector[DLCFundingInputDb],
|
||||
|
@ -63,11 +64,16 @@ case class DLCActionBuilder(dlcWalletDAOs: DLCWalletDAOs) {
|
|||
Unit,
|
||||
NoStream,
|
||||
Effect.Write with Effect.Transactional] = {
|
||||
val dlcDbAction = dlcDAO.updateAction(dlcDb)
|
||||
val inputAction = dlcInputsDAO.createAllAction(offerInputs ++ acceptInputs)
|
||||
val acceptAction = dlcAcceptDAO.createAction(dlcAcceptDb)
|
||||
val sigsAction = dlcSigsDAO.createAllAction(cetSigsDb)
|
||||
val refundSigAction = dlcRefundSigDAO.createAction(refundSigsDb)
|
||||
val actions = Vector(inputAction, acceptAction, sigsAction, refundSigAction)
|
||||
val actions = Vector(dlcDbAction,
|
||||
inputAction,
|
||||
acceptAction,
|
||||
sigsAction,
|
||||
refundSigAction)
|
||||
|
||||
val allActions = DBIO
|
||||
.sequence(actions)
|
||||
|
|
|
@ -45,6 +45,19 @@ object DLCStatusBuilder {
|
|||
totalCollateral,
|
||||
localCollateral
|
||||
)
|
||||
case DLCState.AcceptComputingAdaptorSigs =>
|
||||
AcceptedComputingAdaptorSigs(
|
||||
dlcId = dlcId,
|
||||
isInitiator = dlcDb.isInitiator,
|
||||
lastUpdated = dlcDb.lastUpdated,
|
||||
tempContractId = dlcDb.tempContractId,
|
||||
contractId = dlcDb.contractIdOpt.get,
|
||||
contractInfo = contractInfo,
|
||||
timeouts = contractData.dlcTimeouts,
|
||||
feeRate = dlcDb.feeRate,
|
||||
totalCollateral = totalCollateral,
|
||||
localCollateral = localCollateral
|
||||
)
|
||||
case DLCState.Accepted =>
|
||||
Accepted(
|
||||
dlcId,
|
||||
|
@ -58,6 +71,20 @@ object DLCStatusBuilder {
|
|||
totalCollateral,
|
||||
localCollateral
|
||||
)
|
||||
case DLCState.SignComputingAdaptorSigs =>
|
||||
SignedComputingAdaptorSigs(
|
||||
dlcId = dlcId,
|
||||
isInitiator = dlcDb.isInitiator,
|
||||
lastUpdated = dlcDb.lastUpdated,
|
||||
tempContractId = dlcDb.tempContractId,
|
||||
contractId = dlcDb.contractIdOpt.get,
|
||||
contractInfo = contractInfo,
|
||||
timeouts = contractData.dlcTimeouts,
|
||||
feeRate = dlcDb.feeRate,
|
||||
totalCollateral = totalCollateral,
|
||||
localCollateral = localCollateral,
|
||||
dlcDb.fundingTxIdOpt.get
|
||||
)
|
||||
case DLCState.Signed =>
|
||||
Signed(
|
||||
dlcId,
|
||||
|
|
Loading…
Add table
Reference in a new issue