mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 10:46:42 +01:00
DLC <-> contact mapping (#4346)
* DLC <-> contact mapping
* updated docs
* populate dlc/contact mapping automatically
* typo
* respond to the PR comments
* rename `contact` to `peer`
* fix unit tests
* create a contact when an incoming offers gets created
* drop dlc_contact_mapping table
* fix build
* update the docs
* Revert "update the docs"
This reverts commit 2386adadcd
.
* revert dlc-contact-* endpoints
t Please enter the commit message for your changes. Lines starting
This commit is contained in:
parent
ddbdde495d
commit
fdf281b469
36 changed files with 670 additions and 145 deletions
|
@ -29,6 +29,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Some("127.0.0.1:0")
|
||||
|
||||
val status =
|
||||
DLCStatus.Offered(
|
||||
Sha256Digest.empty,
|
||||
|
@ -40,7 +42,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
offer.feeRate,
|
||||
totalCollateral,
|
||||
offer.collateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Offered)
|
||||
|
@ -66,6 +69,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
"tb1q4ps6c9ewa7uca5v39fakykq9q6hpgjkxje8gve"),
|
||||
true))
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.Accepted(
|
||||
Sha256Digest.empty,
|
||||
|
@ -78,7 +83,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
offer.feeRate,
|
||||
totalCollateral,
|
||||
offer.collateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Accepted)
|
||||
|
@ -100,6 +106,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.Signed(
|
||||
Sha256Digest.empty,
|
||||
|
@ -113,7 +121,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
totalCollateral,
|
||||
offer.collateral,
|
||||
txId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Signed)
|
||||
|
@ -135,6 +144,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.Broadcasted(
|
||||
Sha256Digest.empty,
|
||||
|
@ -148,7 +159,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
totalCollateral,
|
||||
offer.collateral,
|
||||
fundingTxId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Broadcasted)
|
||||
|
@ -170,6 +182,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.Confirmed(
|
||||
Sha256Digest.empty,
|
||||
|
@ -183,7 +197,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
totalCollateral,
|
||||
offer.collateral,
|
||||
fundingTxId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Confirmed)
|
||||
|
@ -216,6 +231,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.Claimed(
|
||||
Sha256Digest.empty,
|
||||
|
@ -234,7 +251,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
outcome,
|
||||
myPayout = myPayout,
|
||||
counterPartyPayout = theirPayout,
|
||||
payoutAddress = payoutAddress
|
||||
payoutAddress = payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Claimed)
|
||||
|
@ -270,6 +288,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.RemoteClaimed(
|
||||
Sha256Digest.empty,
|
||||
|
@ -288,7 +308,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
outcome,
|
||||
myPayout = myPayout,
|
||||
counterPartyPayout = theirPayout,
|
||||
payoutAddress = payoutAddress
|
||||
payoutAddress = payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.RemoteClaimed)
|
||||
|
@ -320,6 +341,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
|
||||
val payoutAddress = Option.empty[PayoutAddress]
|
||||
|
||||
val contact = Option.empty[String]
|
||||
|
||||
val status =
|
||||
DLCStatus.Refunded(
|
||||
Sha256Digest.empty,
|
||||
|
@ -336,7 +359,8 @@ class DLCStatusTest extends BitcoinSJvmTest {
|
|||
closingTxId,
|
||||
myPayout = myPayout,
|
||||
counterPartyPayout = theirPayout,
|
||||
payoutAddress = payoutAddress
|
||||
payoutAddress = payoutAddress,
|
||||
contact
|
||||
)
|
||||
|
||||
assert(status.state == DLCState.Refunded)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.bitcoins.commons.rpc
|
||||
|
||||
import org.bitcoins.core.api.dlc.wallet.db.DLCContactDb
|
||||
import org.bitcoins.crypto.Sha256Digest
|
||||
|
||||
import java.net.{InetSocketAddress, URI}
|
||||
import scala.util.{Failure, Try}
|
||||
|
@ -84,3 +85,53 @@ object ContactRemove {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
case class DLCContactAdd(dlcId: Sha256Digest, address: InetSocketAddress)
|
||||
extends CommandRpc
|
||||
with AppServerCliCommand
|
||||
|
||||
object DLCContactAdd {
|
||||
|
||||
val empty: DLCContactAdd =
|
||||
DLCContactAdd(Sha256Digest.empty,
|
||||
InetSocketAddress.createUnresolved("127.0.0.1", 9999))
|
||||
|
||||
def fromJsArr(arr: ujson.Arr): Try[DLCContactAdd] = {
|
||||
arr.arr.toList match {
|
||||
case dlcIdJs :: addressJs :: Nil =>
|
||||
Try {
|
||||
val dlcId = Sha256Digest.fromHex(dlcIdJs.str)
|
||||
val address = {
|
||||
val uri = new URI(s"tcp://${addressJs.str}")
|
||||
InetSocketAddress.createUnresolved(uri.getHost, uri.getPort)
|
||||
}
|
||||
DLCContactAdd(dlcId, address)
|
||||
}
|
||||
case other =>
|
||||
val exn = new IllegalArgumentException(
|
||||
s"Bad number or arguments to dlc-contact-add, got=${other.length} expected=2")
|
||||
Failure(exn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case class DLCContactRemove(dlcId: Sha256Digest)
|
||||
extends CommandRpc
|
||||
with AppServerCliCommand
|
||||
|
||||
object DLCContactRemove {
|
||||
|
||||
def fromJsArr(arr: ujson.Arr): Try[DLCContactRemove] = {
|
||||
arr.arr.toList match {
|
||||
case dlcIdJs :: Nil =>
|
||||
Try {
|
||||
val dlcId = Sha256Digest.fromHex(dlcIdJs.str)
|
||||
DLCContactRemove(dlcId)
|
||||
}
|
||||
case other =>
|
||||
val exn = new IllegalArgumentException(
|
||||
s"Bad number or arguments to contact-remove, got=${other.length} expected=1")
|
||||
Failure(exn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.bitcoins.commons.serializers.JsonReaders.jsToSatoshis
|
|||
import org.bitcoins.core.api.dlc.wallet.db.{DLCContactDb, IncomingDLCOfferDb}
|
||||
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
||||
import org.bitcoins.core.api.wallet.db.SpendingInfoDb
|
||||
import org.bitcoins.core.config.DLC
|
||||
import org.bitcoins.core.crypto._
|
||||
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
||||
import org.bitcoins.core.dlc.accounting.DLCWalletAccounting
|
||||
|
@ -815,7 +816,13 @@ object Picklers {
|
|||
writer[Value].comap { payoutAddressOpt =>
|
||||
payoutAddressOpt
|
||||
.map(pa => writeJs(pa))
|
||||
.getOrElse(Null)
|
||||
.getOrElse(ujson.Null)
|
||||
}
|
||||
|
||||
implicit val optionContactDbW: Writer[Option[DLCContactDb]] =
|
||||
writer[Value].comap {
|
||||
case Some(contact) => writeContactDb(contact)
|
||||
case None => ujson.Null
|
||||
}
|
||||
|
||||
implicit val offeredW: Writer[Offered] =
|
||||
|
@ -836,7 +843,8 @@ object Picklers {
|
|||
"totalCollateral" -> Num(totalCollateral.satoshis.toLong.toDouble),
|
||||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -859,7 +867,8 @@ object Picklers {
|
|||
"totalCollateral" -> Num(totalCollateral.satoshis.toLong.toDouble),
|
||||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -881,7 +890,8 @@ object Picklers {
|
|||
"totalCollateral" -> Num(totalCollateral.satoshis.toLong.toDouble),
|
||||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -905,7 +915,8 @@ object Picklers {
|
|||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"fundingTxId" -> Str(fundingTxId.hex),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -928,7 +939,8 @@ object Picklers {
|
|||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"fundingTxId" -> Str(fundingTxId.hex),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -952,7 +964,8 @@ object Picklers {
|
|||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"fundingTxId" -> Str(fundingTxId.hex),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -976,7 +989,8 @@ object Picklers {
|
|||
"localCollateral" -> Num(localCollateral.satoshis.toLong.toDouble),
|
||||
"remoteCollateral" -> Num(remoteCollateral.satoshis.toLong.toDouble),
|
||||
"fundingTxId" -> Str(fundingTxId.hex),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1033,8 @@ object Picklers {
|
|||
claimed.counterPartyPayout.satoshis.toLong.toDouble),
|
||||
PicklerKeys.pnl -> Num(claimed.pnl.satoshis.toLong.toDouble),
|
||||
PicklerKeys.rateOfReturn -> Num(claimed.rateOfReturn.toDouble),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1062,7 +1077,8 @@ object Picklers {
|
|||
remoteClaimed.counterPartyPayout.satoshis.toLong.toDouble),
|
||||
PicklerKeys.pnl -> Num(remoteClaimed.pnl.satoshis.toLong.toDouble),
|
||||
PicklerKeys.rateOfReturn -> Num(remoteClaimed.rateOfReturn.toDouble),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1091,7 +1107,8 @@ object Picklers {
|
|||
refunded.counterPartyPayout.satoshis.toLong.toDouble),
|
||||
PicklerKeys.pnl -> Num(refunded.pnl.satoshis.toLong.toDouble),
|
||||
PicklerKeys.rateOfReturn -> Num(refunded.rateOfReturn.toDouble),
|
||||
"payoutAddress" -> writeJs(payoutAddress)
|
||||
"payoutAddress" -> writeJs(payoutAddress),
|
||||
"peer" -> peer.map(p => writeJs(p)).getOrElse(Null)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1163,6 +1180,9 @@ object Picklers {
|
|||
val feeRate = SatoshisPerVirtualByte.fromLong(obj("feeRate").num.toLong)
|
||||
val totalCollateral = Satoshis(obj("totalCollateral").num.toLong)
|
||||
val localCollateral = Satoshis(obj("localCollateral").num.toLong)
|
||||
val peerOpt =
|
||||
if (obj("peer").isNull || !obj.value.contains("peer")) None
|
||||
else Some(obj("peer").str)
|
||||
|
||||
lazy val contractId = ByteVector.fromValidHex(obj("contractId").str)
|
||||
lazy val fundingTxId = DoubleSha256DigestBE(obj("fundingTxId").str)
|
||||
|
@ -1232,7 +1252,8 @@ object Picklers {
|
|||
feeRate,
|
||||
totalCollateral,
|
||||
localCollateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.AcceptComputingAdaptorSigs =>
|
||||
AcceptedComputingAdaptorSigs(
|
||||
|
@ -1246,7 +1267,8 @@ object Picklers {
|
|||
feeRate,
|
||||
totalCollateral,
|
||||
localCollateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.Accepted =>
|
||||
Accepted(
|
||||
|
@ -1260,7 +1282,8 @@ object Picklers {
|
|||
feeRate,
|
||||
totalCollateral,
|
||||
localCollateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.SignComputingAdaptorSigs =>
|
||||
SignedComputingAdaptorSigs(
|
||||
|
@ -1275,7 +1298,8 @@ object Picklers {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
fundingTxId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.Signed =>
|
||||
Signed(
|
||||
|
@ -1290,7 +1314,8 @@ object Picklers {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
fundingTxId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.Broadcasted =>
|
||||
Broadcasted(
|
||||
|
@ -1305,7 +1330,8 @@ object Picklers {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
fundingTxId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.Confirmed =>
|
||||
Confirmed(
|
||||
|
@ -1320,7 +1346,8 @@ object Picklers {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
fundingTxId,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.Claimed =>
|
||||
Claimed(
|
||||
|
@ -1340,7 +1367,8 @@ object Picklers {
|
|||
oracleOutcome,
|
||||
myPayout = myPayoutOpt.get,
|
||||
counterPartyPayout = theirPayoutOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.RemoteClaimed =>
|
||||
require(oracleSigs.size == 1,
|
||||
|
@ -1362,7 +1390,8 @@ object Picklers {
|
|||
oracleOutcome,
|
||||
myPayout = myPayoutOpt.get,
|
||||
counterPartyPayout = theirPayoutOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
case DLCState.Refunded =>
|
||||
Refunded(
|
||||
|
@ -1380,7 +1409,8 @@ object Picklers {
|
|||
closingTxId,
|
||||
myPayout = myPayoutOpt.get,
|
||||
counterPartyPayout = theirPayoutOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
peerOpt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1523,7 +1553,7 @@ object Picklers {
|
|||
private def readContactDb(obj: ujson.Obj): DLCContactDb = {
|
||||
val addressStr = obj(PicklerKeys.addressKey).str
|
||||
val address: InetSocketAddress =
|
||||
NetworkUtil.parseInetSocketAddress(addressStr, 2862)
|
||||
NetworkUtil.parseInetSocketAddress(addressStr, DLC.DefaultPort)
|
||||
DLCContactDb(
|
||||
alias = obj(PicklerKeys.aliasKey).str,
|
||||
address = address,
|
||||
|
|
|
@ -4,6 +4,7 @@ import akka.actor.{ActorSystem, Cancellable}
|
|||
import grizzled.slf4j.Logging
|
||||
import org.bitcoins.cli.CliCommand._
|
||||
import org.bitcoins.cli.ConsoleCli
|
||||
import org.bitcoins.core.config.DLC
|
||||
import org.bitcoins.core.dlc.accounting.RateOfReturnUtil
|
||||
import org.bitcoins.core.serializers.PicklerKeys
|
||||
import org.bitcoins.core.wallet.fee.FeeUnit
|
||||
|
@ -175,7 +176,7 @@ class WalletGUIModel(dlcModel: DLCPaneModel)(implicit system: ActorSystem)
|
|||
}
|
||||
|
||||
// Address returned from GetDLCHostAddress when Tor is disabled
|
||||
private val DEFAULT_TOR_ADDRESS = "0:0:0:0:0:0:0:0:2862"
|
||||
private val DEFAULT_TOR_ADDRESS = "0:0:0:0:0:0:0:0:" + DLC.DefaultPort
|
||||
|
||||
/** Retrieves the tor endpoint address
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.bitcoins.gui.dlc.dialog
|
||||
|
||||
import org.bitcoins.cli.CliCommand._
|
||||
import org.bitcoins.core.config.DLC
|
||||
import org.bitcoins.core.protocol.dlc.models._
|
||||
import org.bitcoins.core.protocol.tlv._
|
||||
import org.bitcoins.core.util.NetworkUtil
|
||||
|
@ -23,7 +24,7 @@ class AcceptOfferDialog extends CliCommandProducer[AcceptDLCCliCommand] {
|
|||
val offer = LnMessageFactory(DLCOfferTLV).fromHex(offerHex)
|
||||
val text = peerAddressTF.text.value.trim
|
||||
if (text.nonEmpty) {
|
||||
val peer = NetworkUtil.parseInetSocketAddress(text, 2862)
|
||||
val peer = NetworkUtil.parseInetSocketAddress(text, DLC.DefaultPort)
|
||||
|
||||
AcceptDLC(offer, peer)
|
||||
} else {
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
|||
import org.bitcoins.core.protocol.dlc.models.ContractInfo
|
||||
import org.bitcoins.core.protocol.tlv.OracleAnnouncementTLV
|
||||
import org.bitcoins.core.serializers.PicklerKeys
|
||||
import org.bitcoins.crypto.Sha256Digest
|
||||
import org.bitcoins.dlc.node.DLCNode
|
||||
import org.bitcoins.server.routes.ServerCommand
|
||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||
|
@ -205,5 +206,43 @@ class DLCRoutesSpec
|
|||
assert(responseAs[String] == s"""{"result":"ok","error":null}""")
|
||||
}
|
||||
}
|
||||
|
||||
"dlc-contact-add a peer" in {
|
||||
(mockWallet
|
||||
.addDLCContactMapping(_: Sha256Digest, _: InetSocketAddress))
|
||||
.expects(Sha256Digest.empty, expected.address)
|
||||
.returning(Future.unit)
|
||||
|
||||
val args =
|
||||
ujson.Arr(ujson.Str(Sha256Digest.empty.hex), ujson.Str(address))
|
||||
|
||||
val route =
|
||||
dlcRoutes.handleCommand(ServerCommand("dlc-contact-add", args))
|
||||
|
||||
Post() ~> route ~> check {
|
||||
assert(contentType == ContentTypes.`application/json`)
|
||||
assert(
|
||||
responseAs[String] == s"""{"result":{"dlcId":"0000000000000000000000000000000000000000000000000000000000000000","contactId":"i3bfhauurptgypgnolqmj7xxv7pcs5c6udtzthbgojc7eaxx6zbbjyad.onion:2862"},"error":null}""")
|
||||
}
|
||||
}
|
||||
|
||||
"dlc-contact-remove a peer" in {
|
||||
|
||||
(mockWallet
|
||||
.removeDLCContactMapping(_: Sha256Digest))
|
||||
.expects(Sha256Digest.empty)
|
||||
.returning(Future.unit)
|
||||
|
||||
val args = ujson.Arr(ujson.Str(Sha256Digest.empty.hex))
|
||||
|
||||
val route =
|
||||
dlcRoutes.handleCommand(ServerCommand("dlc-contact-remove", args))
|
||||
|
||||
Post() ~> route ~> check {
|
||||
assert(contentType == ContentTypes.`application/json`)
|
||||
assert(responseAs[String] == s"""{"result":"ok","error":null}""")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.scalatest.wordspec.AnyWordSpec
|
|||
import scodec.bits.ByteVector
|
||||
import ujson._
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import java.time.{ZoneId, ZonedDateTime}
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
@ -989,6 +990,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
|||
_: Option[SatoshisPerVirtualByte],
|
||||
_: UInt32,
|
||||
_: UInt32,
|
||||
_: Option[InetSocketAddress],
|
||||
_: Option[BitcoinAddress],
|
||||
_: Option[BitcoinAddress]
|
||||
)
|
||||
|
@ -1000,6 +1002,7 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
|||
UInt32(contractMaturity),
|
||||
UInt32(contractTimeout),
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
.returning(Future.successful(offer))
|
||||
|
@ -1059,9 +1062,10 @@ class RoutesSpec extends AnyWordSpec with ScalatestRouteTest with MockFactory {
|
|||
"accept a dlc offer" in {
|
||||
(mockWalletApi
|
||||
.acceptDLCOffer(_: DLCOfferTLV,
|
||||
_: Option[InetSocketAddress],
|
||||
_: Option[BitcoinAddress],
|
||||
_: Option[BitcoinAddress]))
|
||||
.expects(offer.toTLV, None, None)
|
||||
.expects(offer.toTLV, None, None, None)
|
||||
.returning(Future.successful(accept))
|
||||
|
||||
val route = walletRoutes.handleCommand(
|
||||
|
|
|
@ -75,7 +75,8 @@ class WalletRoutesSpec
|
|||
feeRate = null,
|
||||
totalCollateral = null,
|
||||
localCollateral = null,
|
||||
payoutAddress = None
|
||||
payoutAddress = None,
|
||||
peer = None
|
||||
)
|
||||
|
||||
(mockWalletApi.findDLCByTemporaryContractId: Sha256Digest => Future[
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.bitcoins.server
|
|||
import akka.actor.ActorSystem
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.server._
|
||||
import org.bitcoins.commons.rpc.{ContactAdd, ContactRemove}
|
||||
import org.bitcoins.commons.rpc._
|
||||
import org.bitcoins.commons.serializers.Picklers
|
||||
import org.bitcoins.core.api.dlc.node.DLCNodeApi
|
||||
import org.bitcoins.core.api.dlc.wallet.db.IncomingDLCOfferDb
|
||||
|
@ -159,5 +159,32 @@ case class DLCRoutes(dlcNode: DLCNodeApi)(implicit system: ActorSystem)
|
|||
}
|
||||
}
|
||||
|
||||
case ServerCommand("dlc-contact-add", arr) =>
|
||||
withValidServerCommand(DLCContactAdd.fromJsArr(arr)) { dlcContactAdd =>
|
||||
complete {
|
||||
dlcNode.wallet
|
||||
.addDLCContactMapping(dlcContactAdd.dlcId, dlcContactAdd.address)
|
||||
.map { _ =>
|
||||
val dlcId = dlcContactAdd.dlcId.hex
|
||||
val contactId =
|
||||
dlcContactAdd.address.getHostName + ":" + dlcContactAdd.address.getPort
|
||||
Server.httpSuccess(
|
||||
ujson.Obj("dlcId" -> dlcId, "contactId" -> contactId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ServerCommand("dlc-contact-remove", arr) =>
|
||||
withValidServerCommand(DLCContactRemove.fromJsArr(arr)) {
|
||||
dlcContactRemove =>
|
||||
complete {
|
||||
dlcNode.wallet
|
||||
.removeDLCContactMapping(dlcContactRemove.dlcId)
|
||||
.map { _ =>
|
||||
Server.httpSuccess("ok")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParamet
|
|||
import org.bitcoins.commons.jsonmodels.cli.ContractDescriptorParser
|
||||
import org.bitcoins.commons.serializers.JsonReaders
|
||||
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
|
||||
import org.bitcoins.core.config.DLC
|
||||
import org.bitcoins.core.crypto._
|
||||
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
||||
import org.bitcoins.core.hd.AddressType
|
||||
|
@ -15,11 +16,9 @@ import org.bitcoins.core.protocol.tlv._
|
|||
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
|
||||
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
|
||||
import org.bitcoins.core.psbt.PSBT
|
||||
import org.bitcoins.core.util.NetworkUtil
|
||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||
import org.bitcoins.core.wallet.utxo.AddressLabelTag
|
||||
import org.bitcoins.crypto._
|
||||
import org.bitcoins.server.GetDLC.nullToOpt
|
||||
import scodec.bits.ByteVector
|
||||
import ujson._
|
||||
|
||||
|
@ -650,6 +649,27 @@ object SendToAddress extends ServerJsonModels {
|
|||
|
||||
}
|
||||
|
||||
case class GetDLCs(contactId: Option[InetSocketAddress])
|
||||
|
||||
object GetDLCs extends ServerJsonModels {
|
||||
|
||||
def fromJsArr(jsArr: ujson.Arr): Try[GetDLCs] = {
|
||||
jsArr.arr.toList match {
|
||||
case addressJs :: Nil =>
|
||||
Try {
|
||||
val address = jsToInetSocketAddress(addressJs)
|
||||
GetDLCs(Some(address))
|
||||
}
|
||||
case Nil =>
|
||||
Try(GetDLCs(None))
|
||||
case other =>
|
||||
Failure(
|
||||
new IllegalArgumentException(
|
||||
s"Bad number of arguments: ${other.length}. Expected: 1"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case class GetDLC(dlcId: Sha256Digest)
|
||||
|
||||
object GetDLC extends ServerJsonModels {
|
||||
|
@ -678,7 +698,8 @@ case class CreateDLCOffer(
|
|||
locktimeOpt: Option[UInt32],
|
||||
refundLocktime: UInt32,
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress])
|
||||
externalChangeAddressOpt: Option[BitcoinAddress],
|
||||
peerAddressOpt: Option[InetSocketAddress])
|
||||
|
||||
object CreateDLCOffer extends ServerJsonModels {
|
||||
|
||||
|
@ -691,7 +712,8 @@ object CreateDLCOffer extends ServerJsonModels {
|
|||
locktimeJs: Value,
|
||||
refundLTJs: Value,
|
||||
payoutAddressJs: Value,
|
||||
changeAddressJs: Value) = Try {
|
||||
changeAddressJs: Value,
|
||||
peerAddressJs: Value) = Try {
|
||||
val contractInfoTLV = jsToContractInfoTLV(contractInfoJs)
|
||||
val collateral = jsToSatoshis(collateralJs)
|
||||
val feeRate = jsToSatoshisPerVirtualByteOpt(feeRateOptJs)
|
||||
|
@ -704,13 +726,17 @@ object CreateDLCOffer extends ServerJsonModels {
|
|||
val changeAddressJsOpt = nullToOpt(changeAddressJs)
|
||||
val changeAddressOpt =
|
||||
changeAddressJsOpt.map(js => jsToBitcoinAddress(js))
|
||||
val peerAddressJsOpt = nullToOpt(peerAddressJs)
|
||||
val peerAddressOpt = peerAddressJsOpt.map(js => jsToInetSocketAddress(js))
|
||||
|
||||
CreateDLCOffer(contractInfoTLV,
|
||||
collateral,
|
||||
feeRate,
|
||||
locktimeOpt,
|
||||
refundLT,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt)
|
||||
changeAddressOpt,
|
||||
peerAddressOpt)
|
||||
}
|
||||
|
||||
jsArr.arr.toList match {
|
||||
|
@ -721,6 +747,7 @@ object CreateDLCOffer extends ServerJsonModels {
|
|||
locktimeJs,
|
||||
refundLTJs,
|
||||
Null,
|
||||
Null,
|
||||
Null)
|
||||
case contractInfoJs :: collateralJs :: feeRateOptJs :: locktimeJs :: refundLTJs :: payoutAddressJs :: Nil =>
|
||||
parseParameters(contractInfoJs,
|
||||
|
@ -729,6 +756,7 @@ object CreateDLCOffer extends ServerJsonModels {
|
|||
locktimeJs,
|
||||
refundLTJs,
|
||||
payoutAddressJs,
|
||||
Null,
|
||||
Null)
|
||||
case contractInfoJs :: collateralJs :: feeRateOptJs :: locktimeJs :: refundLTJs :: payoutAddressJs :: changeAddressJs :: Nil =>
|
||||
parseParameters(contractInfoJs,
|
||||
|
@ -737,7 +765,17 @@ object CreateDLCOffer extends ServerJsonModels {
|
|||
locktimeJs,
|
||||
refundLTJs,
|
||||
payoutAddressJs,
|
||||
changeAddressJs)
|
||||
changeAddressJs,
|
||||
Null)
|
||||
case contractInfoJs :: collateralJs :: feeRateOptJs :: locktimeJs :: refundLTJs :: payoutAddressJs :: changeAddressJs :: peerAddressJs :: Nil =>
|
||||
parseParameters(contractInfoJs,
|
||||
collateralJs,
|
||||
feeRateOptJs,
|
||||
locktimeJs,
|
||||
refundLTJs,
|
||||
payoutAddressJs,
|
||||
changeAddressJs,
|
||||
peerAddressJs)
|
||||
case other =>
|
||||
Failure(
|
||||
new IllegalArgumentException(
|
||||
|
@ -905,7 +943,8 @@ object DecodeAttestations extends ServerJsonModels {
|
|||
case class AcceptDLCOffer(
|
||||
offer: LnMessage[DLCOfferTLV],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress])
|
||||
externalChangeAddressOpt: Option[BitcoinAddress],
|
||||
peerAddress: Option[InetSocketAddress])
|
||||
|
||||
object AcceptDLCOffer extends ServerJsonModels {
|
||||
|
||||
|
@ -913,7 +952,8 @@ object AcceptDLCOffer extends ServerJsonModels {
|
|||
def parseParameters(
|
||||
offerJs: Value,
|
||||
payoutAddressJs: Value,
|
||||
changeAddressJs: Value) = Try {
|
||||
changeAddressJs: Value,
|
||||
peerAddressJs: Value) = Try {
|
||||
val offer = LnMessageFactory(DLCOfferTLV).fromHex(offerJs.str)
|
||||
val payoutAddressJsOpt = nullToOpt(payoutAddressJs)
|
||||
val payoutAddressOpt =
|
||||
|
@ -921,16 +961,23 @@ object AcceptDLCOffer extends ServerJsonModels {
|
|||
val changeAddressJsOpt = nullToOpt(changeAddressJs)
|
||||
val changeAddressOpt =
|
||||
changeAddressJsOpt.map(js => jsToBitcoinAddress(js))
|
||||
AcceptDLCOffer(offer, payoutAddressOpt, changeAddressOpt)
|
||||
val peerAddressJsOpt = nullToOpt(peerAddressJs)
|
||||
val peerAddress = peerAddressJsOpt.map(js => jsToInetSocketAddress(js))
|
||||
AcceptDLCOffer(offer, payoutAddressOpt, changeAddressOpt, peerAddress)
|
||||
}
|
||||
|
||||
jsArr.arr.toList match {
|
||||
case offerJs :: Nil =>
|
||||
parseParameters(offerJs, Null, Null)
|
||||
parseParameters(offerJs, Null, Null, Null)
|
||||
case offerJs :: payoutAddressJs :: Nil =>
|
||||
parseParameters(offerJs, payoutAddressJs, Null)
|
||||
parseParameters(offerJs, payoutAddressJs, Null, Null)
|
||||
case offerJs :: payoutAddressJs :: changeAddressJs :: Nil =>
|
||||
parseParameters(offerJs, payoutAddressJs, changeAddressJs)
|
||||
parseParameters(offerJs, payoutAddressJs, changeAddressJs, Null)
|
||||
case offerJs :: payoutAddressJs :: changeAddressJs :: peerAddressJs :: Nil =>
|
||||
parseParameters(offerJs,
|
||||
payoutAddressJs,
|
||||
changeAddressJs,
|
||||
peerAddressJs)
|
||||
case Nil =>
|
||||
Failure(new IllegalArgumentException("Missing offer argument"))
|
||||
|
||||
|
@ -963,9 +1010,7 @@ object AcceptDLC extends ServerJsonModels {
|
|||
case Failure(_) => LnMessage(DLCOfferTLV.fromHex(offerJs.str))
|
||||
}
|
||||
|
||||
val uri = new URI("tcp://" + addrJs.str)
|
||||
val peerAddr =
|
||||
InetSocketAddress.createUnresolved(uri.getHost, uri.getPort)
|
||||
val peerAddr = jsToInetSocketAddress(addrJs)
|
||||
val payoutAddressJsOpt = nullToOpt(payoutAddressJs)
|
||||
val payoutAddressOpt =
|
||||
payoutAddressJsOpt.map(js => jsToBitcoinAddress(js))
|
||||
|
@ -1391,7 +1436,7 @@ case class OfferAdd(
|
|||
peer: Option[String],
|
||||
message: Option[String])
|
||||
|
||||
object OfferAdd {
|
||||
object OfferAdd extends ServerJsonModels {
|
||||
|
||||
def fromJsArr(arr: ujson.Arr): Try[OfferAdd] = {
|
||||
arr.arr.toList match {
|
||||
|
@ -1435,14 +1480,14 @@ case class OfferSend(
|
|||
message: String,
|
||||
offerE: Either[DLCOfferTLV, Sha256Digest])
|
||||
|
||||
object OfferSend {
|
||||
object OfferSend extends ServerJsonModels {
|
||||
|
||||
def fromJsArr(arr: ujson.Arr): Try[OfferSend] = {
|
||||
arr.arr.toList match {
|
||||
case offerJs :: peerAddressJs :: messageJs :: Nil =>
|
||||
Try {
|
||||
val peerAddress =
|
||||
NetworkUtil.parseInetSocketAddress(peerAddressJs.str, 2862)
|
||||
jsToInetSocketAddress(peerAddressJs, DLC.DefaultPort)
|
||||
val message = messageJs.str
|
||||
val offerE =
|
||||
Try(LnMessageFactory(DLCOfferTLV).fromHex(offerJs.str).tlv)
|
||||
|
@ -1598,4 +1643,17 @@ trait ServerJsonModels {
|
|||
js.arr.foldLeft(Vector.empty[OracleAttestmentTLV])((vec, tlv) =>
|
||||
vec :+ jsToOracleAttestmentTLV(tlv))
|
||||
}
|
||||
|
||||
def jsToInetSocketAddress(
|
||||
js: Value,
|
||||
defaultPort: Int = -1): InetSocketAddress = {
|
||||
js match {
|
||||
case str: Str =>
|
||||
val uri = new URI("tcp://" + str.str)
|
||||
val port = if (uri.getPort >= 0) uri.getPort else defaultPort
|
||||
InetSocketAddress.createUnresolved(uri.getHost, port)
|
||||
case _: Value =>
|
||||
throw Value.InvalidData(js, "Expected a host address")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -300,12 +300,23 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit
|
|||
}
|
||||
}
|
||||
|
||||
case ServerCommand("getdlcs", _) =>
|
||||
case ServerCommand("getdlcs", arr) =>
|
||||
GetDLCs.fromJsArr(arr) match {
|
||||
case Success(GetDLCs(Some(contactId))) =>
|
||||
complete {
|
||||
wallet.listDLCsByContact(contactId).map { dlcs =>
|
||||
Server.httpSuccess(dlcs.map(writeJs(_)))
|
||||
}
|
||||
}
|
||||
case Success(GetDLCs(None)) =>
|
||||
complete {
|
||||
wallet.listDLCs().map { dlcs =>
|
||||
Server.httpSuccess(dlcs.map(writeJs(_)))
|
||||
}
|
||||
}
|
||||
case Failure(exception) =>
|
||||
complete(Server.httpBadRequest(exception))
|
||||
}
|
||||
|
||||
case ServerCommand("getdlc", arr) =>
|
||||
GetDLC.fromJsArr(arr) match {
|
||||
|
@ -344,7 +355,8 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit
|
|||
locktimeOpt,
|
||||
refundLT,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt)) =>
|
||||
changeAddressOpt,
|
||||
peerAddressOpt)) =>
|
||||
complete {
|
||||
val announcements = contractInfo.oracleInfo match {
|
||||
case OracleInfoV0TLV(announcement) => Vector(announcement)
|
||||
|
@ -365,6 +377,7 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit
|
|||
feeRateOpt,
|
||||
locktime,
|
||||
refundLT,
|
||||
peerAddressOpt,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt)
|
||||
case None =>
|
||||
|
@ -373,6 +386,7 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit
|
|||
collateral,
|
||||
feeRateOpt,
|
||||
refundLT,
|
||||
peerAddressOpt,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt)
|
||||
}
|
||||
|
@ -388,10 +402,16 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit
|
|||
case Failure(exception) =>
|
||||
complete(Server.httpBadRequest(exception))
|
||||
case Success(
|
||||
AcceptDLCOffer(offer, payoutAddressOpt, changeAddressOpt)) =>
|
||||
AcceptDLCOffer(offer,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt,
|
||||
peerAddressOpt)) =>
|
||||
complete {
|
||||
wallet
|
||||
.acceptDLCOffer(offer.tlv, payoutAddressOpt, changeAddressOpt)
|
||||
.acceptDLCOffer(offer.tlv,
|
||||
peerAddressOpt,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt)
|
||||
.map { accept =>
|
||||
Server.httpSuccess(accept.toMessage.hex)
|
||||
}
|
||||
|
@ -415,6 +435,7 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit
|
|||
|
||||
wallet
|
||||
.acceptDLCOffer(offerMessage.tlv,
|
||||
None,
|
||||
payoutAddressOpt,
|
||||
changeAddressOpt)
|
||||
.map { accept =>
|
||||
|
|
|
@ -28,6 +28,7 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
collateral: Satoshis,
|
||||
feeRateOpt: Option[SatoshisPerVirtualByte],
|
||||
refundLT: UInt32,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] = {
|
||||
val contractInfo = ContractInfo.fromTLV(contractInfoTLV)
|
||||
|
@ -35,6 +36,7 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
collateral,
|
||||
feeRateOpt,
|
||||
refundLT,
|
||||
peerAddressOpt,
|
||||
externalPayoutAddressOpt,
|
||||
externalChangeAddressOpt)
|
||||
}
|
||||
|
@ -45,6 +47,7 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
feeRateOpt: Option[SatoshisPerVirtualByte],
|
||||
locktime: UInt32,
|
||||
refundLT: UInt32,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] = {
|
||||
val contractInfo = ContractInfo.fromTLV(contractInfoTLV)
|
||||
|
@ -53,6 +56,7 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
feeRateOpt,
|
||||
locktime,
|
||||
refundLT,
|
||||
peerAddressOpt,
|
||||
externalPayoutAddressOpt,
|
||||
externalChangeAddressOpt)
|
||||
}
|
||||
|
@ -62,6 +66,7 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
collateral: Satoshis,
|
||||
feeRateOpt: Option[SatoshisPerVirtualByte],
|
||||
refundLT: UInt32,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer]
|
||||
|
||||
|
@ -71,32 +76,24 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
feeRateOpt: Option[SatoshisPerVirtualByte],
|
||||
locktime: UInt32,
|
||||
refundLT: UInt32,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer]
|
||||
|
||||
def registerDLCOffer(dlcOffer: DLCOffer): Future[DLCOffer] = {
|
||||
createDLCOffer(
|
||||
dlcOffer.contractInfo,
|
||||
dlcOffer.collateral,
|
||||
Some(dlcOffer.feeRate),
|
||||
dlcOffer.timeouts.contractMaturity.toUInt32,
|
||||
dlcOffer.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None
|
||||
)
|
||||
}
|
||||
|
||||
def acceptDLCOffer(
|
||||
dlcOfferTLV: DLCOfferTLV,
|
||||
peerAddress: Option[InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCAccept] = {
|
||||
acceptDLCOffer(DLCOffer.fromTLV(dlcOfferTLV),
|
||||
peerAddress,
|
||||
externalPayoutAddressOpt,
|
||||
externalChangeAddressOpt)
|
||||
}
|
||||
|
||||
def acceptDLCOffer(
|
||||
dlcOffer: DLCOffer,
|
||||
peerAddress: Option[InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCAccept]
|
||||
|
||||
|
@ -170,6 +167,14 @@ trait DLCWalletApi { self: WalletApi =>
|
|||
def removeDLCContact(address: InetSocketAddress): Future[Unit]
|
||||
|
||||
def findDLCContacts(alias: String): Future[Vector[DLCContactDb]]
|
||||
|
||||
def addDLCContactMapping(
|
||||
dlcId: Sha256Digest,
|
||||
contactId: InetSocketAddress): Future[Unit]
|
||||
|
||||
def removeDLCContactMapping(dlcId: Sha256Digest): Future[Unit]
|
||||
|
||||
def listDLCsByContact(address: InetSocketAddress): Future[Vector[DLCStatus]]
|
||||
}
|
||||
|
||||
/** An HDWallet that supports DLCs and Neutrino method of syncing */
|
||||
|
|
|
@ -1,5 +1,20 @@
|
|||
package org.bitcoins.core.api.dlc.wallet.db
|
||||
|
||||
import org.bitcoins.core.config.DLC
|
||||
import org.bitcoins.core.util.NetworkUtil
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
|
||||
case class DLCContactDb(alias: String, address: InetSocketAddress, memo: String)
|
||||
|
||||
object DLCContactDbHelper {
|
||||
|
||||
def fromPeerAddress(peerAddress: String): DLCContactDb =
|
||||
DLCContactDb(
|
||||
alias = "",
|
||||
address =
|
||||
NetworkUtil.parseInetSocketAddress(peerAddress, DLC.DefaultPort),
|
||||
memo = ""
|
||||
)
|
||||
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ case class DLCDb(
|
|||
fundingTxIdOpt: Option[DoubleSha256DigestBE],
|
||||
closingTxIdOpt: Option[DoubleSha256DigestBE],
|
||||
aggregateSignatureOpt: Option[SchnorrDigitalSignature],
|
||||
serializationVersion: DLCSerializationVersion
|
||||
serializationVersion: DLCSerializationVersion,
|
||||
peerOpt: Option[String]
|
||||
) extends LastUpdatedDb {
|
||||
|
||||
def updateState(newState: DLCState): DLCDb = {
|
||||
|
@ -61,4 +62,8 @@ case class DLCDb(
|
|||
def updateAggregateSignature(sig: SchnorrDigitalSignature): DLCDb = {
|
||||
copy(aggregateSignatureOpt = Some(sig), lastUpdated = TimeUtil.now)
|
||||
}
|
||||
|
||||
def updatePeer(peer: String): DLCDb = {
|
||||
copy(peerOpt = Some(peer))
|
||||
}
|
||||
}
|
||||
|
|
7
core/src/main/scala/org/bitcoins/core/config/DLC.scala
Normal file
7
core/src/main/scala/org/bitcoins/core/config/DLC.scala
Normal file
|
@ -0,0 +1,7 @@
|
|||
package org.bitcoins.core.config
|
||||
|
||||
object DLC {
|
||||
|
||||
val DefaultPort: Int = 2862
|
||||
|
||||
}
|
|
@ -35,6 +35,7 @@ sealed trait DLCStatus {
|
|||
def localCollateral: CurrencyUnit
|
||||
def remoteCollateral: CurrencyUnit = totalCollateral - localCollateral
|
||||
def payoutAddress: Option[PayoutAddress]
|
||||
def peer(): Option[String]
|
||||
|
||||
lazy val announcements: Vector[OracleAnnouncementTLV] = {
|
||||
oracleInfos.flatMap(_.singleOracleInfos.map(_.announcement))
|
||||
|
@ -92,7 +93,8 @@ object DLCStatus {
|
|||
feeRate: FeeUnit,
|
||||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
payoutAddress: Option[PayoutAddress]
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String]
|
||||
) extends DLCStatus {
|
||||
override val state: DLCState.Offered.type = DLCState.Offered
|
||||
}
|
||||
|
@ -108,7 +110,8 @@ object DLCStatus {
|
|||
feeRate: FeeUnit,
|
||||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends AcceptedDLCStatus {
|
||||
|
||||
override val state: DLCState.AcceptComputingAdaptorSigs.type =
|
||||
|
@ -126,7 +129,8 @@ object DLCStatus {
|
|||
feeRate: FeeUnit,
|
||||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends AcceptedDLCStatus {
|
||||
override val state: DLCState.Accepted.type = DLCState.Accepted
|
||||
}
|
||||
|
@ -143,7 +147,8 @@ object DLCStatus {
|
|||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
fundingTxId: DoubleSha256DigestBE,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends SignedDLCStatus {
|
||||
|
||||
override val state: DLCState.SignComputingAdaptorSigs.type =
|
||||
|
@ -162,7 +167,8 @@ object DLCStatus {
|
|||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
fundingTxId: DoubleSha256DigestBE,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends SignedDLCStatus {
|
||||
override val state: DLCState.Signed.type = DLCState.Signed
|
||||
}
|
||||
|
@ -179,7 +185,8 @@ object DLCStatus {
|
|||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
fundingTxId: DoubleSha256DigestBE,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends SignedDLCStatus {
|
||||
override val state: DLCState.Broadcasted.type = DLCState.Broadcasted
|
||||
}
|
||||
|
@ -196,7 +203,8 @@ object DLCStatus {
|
|||
totalCollateral: CurrencyUnit,
|
||||
localCollateral: CurrencyUnit,
|
||||
fundingTxId: DoubleSha256DigestBE,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends SignedDLCStatus {
|
||||
override val state: DLCState.Confirmed.type = DLCState.Confirmed
|
||||
}
|
||||
|
@ -218,7 +226,8 @@ object DLCStatus {
|
|||
oracleOutcome: OracleOutcome,
|
||||
myPayout: CurrencyUnit,
|
||||
counterPartyPayout: CurrencyUnit,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends ClaimedDLCStatus {
|
||||
override val state: DLCState.Claimed.type = DLCState.Claimed
|
||||
}
|
||||
|
@ -240,7 +249,8 @@ object DLCStatus {
|
|||
oracleOutcome: OracleOutcome,
|
||||
myPayout: CurrencyUnit,
|
||||
counterPartyPayout: CurrencyUnit,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends ClaimedDLCStatus {
|
||||
override val state: DLCState.RemoteClaimed.type = DLCState.RemoteClaimed
|
||||
override val oracleSigs: Vector[SchnorrDigitalSignature] = Vector(oracleSig)
|
||||
|
@ -261,7 +271,8 @@ object DLCStatus {
|
|||
closingTxId: DoubleSha256DigestBE,
|
||||
myPayout: CurrencyUnit,
|
||||
counterPartyPayout: CurrencyUnit,
|
||||
payoutAddress: Option[PayoutAddress])
|
||||
payoutAddress: Option[PayoutAddress],
|
||||
peer: Option[String])
|
||||
extends ClosedDLCStatus {
|
||||
override val state: DLCState.Refunded.type = DLCState.Refunded
|
||||
}
|
||||
|
|
|
@ -83,13 +83,13 @@ class DbManagementTest extends BitcoinSAsyncTest with EmbeddedPg {
|
|||
val result = dlcDbManagement.migrate()
|
||||
dlcAppConfig.driver match {
|
||||
case SQLite =>
|
||||
val expected = 7
|
||||
val expected = 8
|
||||
assert(result.migrationsExecuted == expected)
|
||||
val flywayInfo = dlcAppConfig.info()
|
||||
assert(flywayInfo.applied().length == expected)
|
||||
assert(flywayInfo.pending().length == 0)
|
||||
case PostgreSQL =>
|
||||
val expected = 8
|
||||
val expected = 9
|
||||
assert(result.migrationsExecuted == expected)
|
||||
val flywayInfo = dlcAppConfig.info()
|
||||
|
||||
|
|
|
@ -56,8 +56,9 @@ class DLCNegotiationTest extends BitcoinSDualWalletTest {
|
|||
UInt32.zero,
|
||||
UInt32.one,
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
accept <- walletA.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletA.acceptDLCOffer(offer, None, None, None)
|
||||
|
||||
// Send accept message to begin p2p
|
||||
_ = handler ! DLCDataHandler.Received(accept.toMessage)
|
||||
|
@ -108,6 +109,7 @@ class DLCNegotiationTest extends BitcoinSDualWalletTest {
|
|||
UInt32.zero,
|
||||
UInt32.one,
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
tlv = SendOfferTLV(peer = "peer", message = "msg", offer = offer.toTLV)
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ class DLCNodeTest extends BitcoinSDLCNodeTest {
|
|||
UInt32.zero,
|
||||
UInt32.one,
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
|
||||
_ <- nodeB.acceptDLCOffer(addrA, offer.toMessage, None, None)
|
||||
|
|
|
@ -66,6 +66,7 @@ case class DLCNode(wallet: DLCWalletApi)(implicit
|
|||
for {
|
||||
handler <- connectToPeer(peerAddress)
|
||||
accept <- wallet.acceptDLCOffer(dlcOffer.tlv,
|
||||
Some(peerAddress),
|
||||
externalPayoutAddress,
|
||||
externalChangeAddress)
|
||||
} yield {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.bitcoins.dlc.wallet
|
||||
|
||||
import org.bitcoins.core.api.dlc.wallet.db.DLCDb
|
||||
import org.bitcoins.core.api.dlc.wallet.db.{DLCContactDb, DLCDb}
|
||||
import org.bitcoins.core.api.wallet.db.TransactionDbHelper
|
||||
import org.bitcoins.core.currency.Satoshis
|
||||
import org.bitcoins.core.number.{UInt32, UInt64}
|
||||
|
@ -17,6 +17,8 @@ import org.bitcoins.testkit.fixtures.DLCDAOFixture
|
|||
import org.bitcoins.testkit.wallet.{BitcoinSWalletTest, DLCWalletUtil}
|
||||
import org.scalatest.Assertion
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import java.sql.SQLException
|
||||
import scala.concurrent.Future
|
||||
|
||||
class DLCDAOTest extends BitcoinSWalletTest with DLCDAOFixture {
|
||||
|
@ -219,4 +221,39 @@ class DLCDAOTest extends BitcoinSWalletTest with DLCDAOFixture {
|
|||
|
||||
verifyDatabaseInsertion(tx, tx.txIdBE, remoteTxDAO, daos.dlcDAO)
|
||||
}
|
||||
|
||||
it should "update peer" in { daos =>
|
||||
val contact = DLCContactDb(
|
||||
address = InetSocketAddress.createUnresolved("127.0.0.1", 1),
|
||||
alias = "alias",
|
||||
memo = "memo"
|
||||
)
|
||||
for {
|
||||
// no contact
|
||||
_ <- recoverToSucceededIf[SQLException](
|
||||
daos.dlcDAO.updateDLCContactMapping(dlcId, contact.address))
|
||||
|
||||
_ <- daos.contactDAO.create(contact)
|
||||
|
||||
// no dlc
|
||||
_ <- recoverToSucceededIf[SQLException](
|
||||
daos.dlcDAO.updateDLCContactMapping(dlcId, contact.address))
|
||||
_ <- recoverToSucceededIf[SQLException](
|
||||
daos.dlcDAO.deleteDLCContactMapping(dlcId))
|
||||
|
||||
created <- daos.dlcDAO.create(dlcDb)
|
||||
|
||||
_ <- daos.dlcDAO.updateDLCContactMapping(dlcId, contact.address)
|
||||
|
||||
updated <- daos.dlcDAO.read(dlcId)
|
||||
|
||||
_ <- daos.dlcDAO.deleteDLCContactMapping(dlcId)
|
||||
|
||||
deleted <- daos.dlcDAO.read(dlcId)
|
||||
} yield {
|
||||
assert(created.peerOpt.isEmpty)
|
||||
assert(updated.get.peerOpt == Some("127.0.0.1:1"))
|
||||
assert(deleted.get.peerOpt.isEmpty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -371,6 +371,7 @@ class DLCExecutionTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
|
@ -424,6 +425,7 @@ class DLCExecutionTest extends BitcoinSDualWalletTest {
|
|||
UInt32.zero,
|
||||
UInt32.one,
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
|
||||
_ <- walletA.listDLCs()
|
||||
|
@ -481,10 +483,11 @@ class DLCExecutionTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = Some(SatoshisPerVirtualByte.fromLong(10)),
|
||||
locktime = dummyTimeouts.contractMaturity.toUInt32,
|
||||
refundLocktime = dummyTimeouts.contractTimeout.toUInt32,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
sign <- walletA.signDLC(accept)
|
||||
contractId = sign.contractId
|
||||
(_, sig) = DLCWalletUtil.getSigs(contractInfo)
|
||||
|
|
|
@ -53,6 +53,7 @@ class MultiWalletDLCTest extends BitcoinSWalletTest {
|
|||
UInt32.zero,
|
||||
UInt32.one,
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
dlcsA <- walletA.listDLCs()
|
||||
dlcsB <- walletB.listDLCs()
|
||||
|
@ -76,6 +77,7 @@ class MultiWalletDLCTest extends BitcoinSWalletTest {
|
|||
feeRateOpt = Some(SatoshisPerVirtualByte.one),
|
||||
locktime = UInt32.zero,
|
||||
refundLocktime = UInt32.one,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.bitcoins.testkit.wallet.FundWalletUtil.FundedDLCWallet
|
|||
import org.bitcoins.testkit.wallet.{BitcoinSDualWalletTest, DLCWalletUtil}
|
||||
import org.scalatest.{Assertion, FutureOutcome}
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import scala.concurrent.Future
|
||||
import scala.reflect.ClassTag
|
||||
|
||||
|
@ -47,6 +48,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
@ -64,7 +66,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
assert(offer.changeAddress.value.nonEmpty)
|
||||
}
|
||||
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
dlcB1Opt <- walletB.dlcDAO.read(dlcId)
|
||||
_ = {
|
||||
assert(dlcB1Opt.isDefined)
|
||||
|
@ -189,11 +191,12 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
|
||||
// reorder dlc inputs in wallets
|
||||
_ <- reorderInputDbs(walletA, dlcId)
|
||||
|
@ -248,11 +251,12 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
||||
accept <- walletB.acceptDLCOffer(offer.toTLV, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer.toTLV, None, None, None)
|
||||
|
||||
// reorder dlc inputs in wallets
|
||||
_ <- reorderInputDbs(walletA, dlcId)
|
||||
|
@ -279,6 +283,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
@ -295,7 +300,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
assert(offer.changeAddress.value.nonEmpty)
|
||||
}
|
||||
|
||||
accept <- walletB.acceptDLCOffer(offer.toTLV, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer.toTLV, None, None, None)
|
||||
dlcB1Opt <- walletB.dlcDAO.read(dlcId)
|
||||
_ = {
|
||||
assert(dlcB1Opt.isDefined)
|
||||
|
@ -374,10 +379,11 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
} yield accept
|
||||
}
|
||||
|
||||
|
@ -520,6 +526,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
|
||||
|
@ -565,9 +572,10 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
_ <- walletB.acceptDLCOffer(offer, None, None)
|
||||
_ <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
|
||||
dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
||||
|
@ -608,9 +616,10 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
sign <- walletA.signDLC(accept)
|
||||
_ <- walletB.addDLCSigs(sign)
|
||||
|
||||
|
@ -652,9 +661,10 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
sign <- walletA.signDLC(accept)
|
||||
_ <- walletB.addDLCSigs(sign)
|
||||
|
||||
|
@ -687,9 +697,10 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
UInt32.max,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
sign <- walletA.signDLC(accept)
|
||||
_ <- walletB.addDLCSigs(sign)
|
||||
|
||||
|
@ -754,6 +765,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
_ = {
|
||||
|
@ -768,7 +780,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
|
||||
dlcId = calcDLCId(offer.fundingInputs.map(_.outPoint))
|
||||
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
_ = {
|
||||
assert(accept.fundingInputs.nonEmpty)
|
||||
assert(accept.collateral == offer.contractInfo.max - offer.collateral)
|
||||
|
@ -851,6 +863,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
|
@ -860,8 +873,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerA <- makeOffer(contractInfoA)
|
||||
offerB <- makeOffer(contractInfoB)
|
||||
|
||||
_ <- walletB.acceptDLCOffer(offerA, None, None)
|
||||
_ <- walletB.acceptDLCOffer(offerB, None, None)
|
||||
_ <- walletB.acceptDLCOffer(offerA, None, None, None)
|
||||
_ <- walletB.acceptDLCOffer(offerB, None, None, None)
|
||||
} yield succeed
|
||||
}
|
||||
|
||||
|
@ -899,6 +912,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
|
@ -906,8 +920,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
|
||||
for {
|
||||
offer <- makeOffer(contractInfoA)
|
||||
accept1F = walletB.acceptDLCOffer(offer, None, None)
|
||||
accept2F = walletB.acceptDLCOffer(offer, None, None)
|
||||
accept1F = walletB.acceptDLCOffer(offer, None, None, None)
|
||||
accept2F = walletB.acceptDLCOffer(offer, None, None, None)
|
||||
_ <- recoverToSucceededIf[DuplicateOfferException](
|
||||
Future.sequence(Seq(accept1F, accept2F)))
|
||||
} yield {
|
||||
|
@ -930,6 +944,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
|
@ -937,8 +952,8 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
|
||||
for {
|
||||
offer <- makeOffer(contractInfoA)
|
||||
accept1 <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept2 <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept1 <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
accept2 <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
} yield {
|
||||
assert(accept1 == accept2)
|
||||
}
|
||||
|
@ -958,9 +973,10 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
UInt32.max,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer, None, None, None)
|
||||
res <- recoverToSucceededIf[IllegalArgumentException](
|
||||
walletB.signDLC(accept))
|
||||
} yield res
|
||||
|
@ -981,6 +997,7 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
UInt32.max,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
))
|
||||
} yield {
|
||||
|
@ -1006,12 +1023,13 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
invalidOffer = offer.copy(contractInfo = invalidContractInfo)
|
||||
res <- recoverToSucceededIf[InvalidAnnouncementSignature](
|
||||
walletB.acceptDLCOffer(invalidOffer, None, None))
|
||||
walletB.acceptDLCOffer(invalidOffer, None, None, None))
|
||||
} yield {
|
||||
res
|
||||
}
|
||||
|
@ -1042,6 +1060,12 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
Some(BitcoinAddress.fromString("2MsM67NLa71fHvTUBqNENW15P68nHB2vVXb"))
|
||||
val changeAddressBOpt =
|
||||
Some(BitcoinAddress.fromString("2N4YXTxKEso3yeYXNn5h42Vqu3FzTTQ8Lq5"))
|
||||
val peerAddressOpt1 =
|
||||
Some(InetSocketAddress.createUnresolved("127.0.0.1", 1))
|
||||
val peerAddressOpt2 =
|
||||
Some(InetSocketAddress.createUnresolved("127.0.0.1", 2))
|
||||
val peerAddressOpt3 =
|
||||
Some(InetSocketAddress.createUnresolved("127.0.0.1", 3))
|
||||
|
||||
for {
|
||||
offer <- walletA.createDLCOffer(
|
||||
|
@ -1050,10 +1074,12 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = peerAddressOpt1,
|
||||
externalPayoutAddressOpt = payoutAddressAOpt,
|
||||
externalChangeAddressOpt = changeAddressAOpt
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer,
|
||||
peerAddressOpt2,
|
||||
payoutAddressBOpt,
|
||||
changeAddressBOpt)
|
||||
offer1 <- walletA.createDLCOffer(
|
||||
|
@ -1062,10 +1088,11 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
feeRateOpt = feeRateOpt1,
|
||||
locktime = UInt32.zero,
|
||||
refundLT = UInt32.one,
|
||||
peerAddressOpt = peerAddressOpt3,
|
||||
externalPayoutAddressOpt = None,
|
||||
externalChangeAddressOpt = None
|
||||
)
|
||||
accept1 <- walletB.acceptDLCOffer(offer1, None, None)
|
||||
accept1 <- walletB.acceptDLCOffer(offer1, peerAddressOpt3, None, None)
|
||||
} yield {
|
||||
assert(offer.pubKeys.payoutAddress == payoutAddressAOpt.get)
|
||||
assert(offer.changeAddress == changeAddressAOpt.get)
|
||||
|
@ -1101,10 +1128,11 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
//accept it for the first time using the inputs
|
||||
_ <- walletB.acceptDLCOffer(offer1.toTLV, None, None)
|
||||
_ <- walletB.acceptDLCOffer(offer1.toTLV, None, None, None)
|
||||
//cancel the offer
|
||||
_ <- walletA.cancelDLC(dlcId = offer1.dlcId)
|
||||
|
||||
|
@ -1115,9 +1143,10 @@ class WalletDLCSetupTest extends BitcoinSDualWalletTest {
|
|||
offerData2.timeouts.contractMaturity.toUInt32,
|
||||
offerData2.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
_ <- walletB.acceptDLCOffer(offer2.toTLV, None, None)
|
||||
_ <- walletB.acceptDLCOffer(offer2.toTLV, None, None, None)
|
||||
} yield succeed
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,9 +33,10 @@ class DLCDataManagementTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer1, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer1, None, None, None)
|
||||
contractId = DLCUtil.calcContractId(offer1, accept)
|
||||
acceptDbStateOpt <- walletB.dlcDataManagement.getDLCFundingData(
|
||||
contractId,
|
||||
|
@ -62,9 +63,10 @@ class DLCDataManagementTest extends BitcoinSDualWalletTest {
|
|||
offerData.timeouts.contractMaturity.toUInt32,
|
||||
offerData.timeouts.contractTimeout.toUInt32,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer1, None, None)
|
||||
accept <- walletB.acceptDLCOffer(offer1, None, None, None)
|
||||
|
||||
sign <- walletA.signDLC(accept)
|
||||
signDbStateOpt <- walletA.dlcDataManagement.getDLCFundingData(
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE "global_dlc_data" ADD COLUMN "peer" VARCHAR(1024);
|
||||
|
||||
CREATE INDEX "global_dlc_data_peer_idx" ON "global_dlc_data"("peer");
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE "global_dlc_data" ADD COLUMN "peer" VARCHAR(1024);
|
||||
|
||||
CREATE INDEX "global_dlc_data_peer_idx" ON "global_dlc_data"("peer");
|
|
@ -43,6 +43,7 @@ import org.bitcoins.wallet.{Wallet, WalletLogger}
|
|||
import scodec.bits.ByteVector
|
||||
import slick.dbio.{DBIO, DBIOAction}
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
/** A [[Wallet]] with full DLC Functionality */
|
||||
|
@ -273,6 +274,7 @@ abstract class DLCWallet
|
|||
collateral: Satoshis,
|
||||
feeRateOpt: Option[SatoshisPerVirtualByte],
|
||||
refundLT: UInt32,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] = {
|
||||
chainQueryApi.getBestHashBlockHeight().flatMap { height =>
|
||||
|
@ -281,6 +283,7 @@ abstract class DLCWallet
|
|||
feeRateOpt,
|
||||
locktime = UInt32(height),
|
||||
refundLT,
|
||||
peerAddressOpt,
|
||||
externalPayoutAddressOpt,
|
||||
externalChangeAddressOpt)
|
||||
}
|
||||
|
@ -297,6 +300,7 @@ abstract class DLCWallet
|
|||
feeRateOpt: Option[SatoshisPerVirtualByte],
|
||||
locktime: UInt32,
|
||||
refundLocktime: UInt32,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] = {
|
||||
logger.info("Creating DLC Offer")
|
||||
|
@ -434,7 +438,8 @@ abstract class DLCWallet
|
|||
fundingTxIdOpt = None,
|
||||
closingTxIdOpt = None,
|
||||
aggregateSignatureOpt = None,
|
||||
serializationVersion = contractInfo.serializationVersion
|
||||
serializationVersion = contractInfo.serializationVersion,
|
||||
peerOpt = peerAddressOpt.map(a => a.getHostString + ":" + a.getPort)
|
||||
)
|
||||
|
||||
contractDataDb = DLCContractDataDb(
|
||||
|
@ -485,6 +490,7 @@ abstract class DLCWallet
|
|||
txBuilder: RawTxBuilderWithFinalizer[ShufflingNonInteractiveFinalizer],
|
||||
spendingInfos: Vector[ScriptSignatureParams[InputInfo]],
|
||||
collateral: CurrencyUnit,
|
||||
peerAddressOpt: Option[InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]
|
||||
): Future[InitializedAccept] = {
|
||||
|
@ -553,13 +559,16 @@ abstract class DLCWallet
|
|||
(dlcAcceptWithoutSigs, dlcPubKeys) <- acceptWithoutSigsWithKeysF
|
||||
nextIndex <- nextIndexF
|
||||
contractId = DLCUtil.calcContractId(offer, dlcAcceptWithoutSigs)
|
||||
dlc = DLCAcceptUtil.buildAcceptDlcDb(offer,
|
||||
dlc = DLCAcceptUtil.buildAcceptDlcDb(
|
||||
offer,
|
||||
dlcId,
|
||||
Some(contractId),
|
||||
account,
|
||||
chainType,
|
||||
nextIndex,
|
||||
contractInfo)
|
||||
contractInfo,
|
||||
peerOpt =
|
||||
peerAddressOpt.map(a => a.getHostString + ":" + a.getPort))
|
||||
acceptDb = DLCAcceptUtil.buildAcceptDb(dlc = dlc,
|
||||
acceptWithoutSigs =
|
||||
dlcAcceptWithoutSigs,
|
||||
|
@ -662,6 +671,7 @@ abstract class DLCWallet
|
|||
*/
|
||||
override def acceptDLCOffer(
|
||||
offer: DLCOffer,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCAccept] = {
|
||||
logger.debug("Calculating relevant wallet data for DLC Accept")
|
||||
|
@ -693,6 +703,7 @@ abstract class DLCWallet
|
|||
case None =>
|
||||
createNewDLCAccept(collateral,
|
||||
offer,
|
||||
peerAddressOpt,
|
||||
externalPayoutAddressOpt,
|
||||
externalChangeAddressOpt)
|
||||
}
|
||||
|
@ -744,6 +755,7 @@ abstract class DLCWallet
|
|||
private def createNewDLCAccept(
|
||||
collateral: CurrencyUnit,
|
||||
offer: DLCOffer,
|
||||
peerAddressOpt: Option[java.net.InetSocketAddress],
|
||||
externalPayoutAddressOpt: Option[BitcoinAddress],
|
||||
externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCAccept] =
|
||||
Future {
|
||||
|
@ -764,7 +776,8 @@ abstract class DLCWallet
|
|||
spendingInfos = spendingInfos,
|
||||
collateral = collateral,
|
||||
externalPayoutAddressOpt = externalPayoutAddressOpt,
|
||||
externalChangeAddressOpt = externalChangeAddressOpt
|
||||
externalChangeAddressOpt = externalChangeAddressOpt,
|
||||
peerAddressOpt = peerAddressOpt
|
||||
)
|
||||
_ = require(
|
||||
initializedAccept.acceptWithoutSigs.tempContractId == offer.tempContractId,
|
||||
|
@ -1696,8 +1709,24 @@ abstract class DLCWallet
|
|||
}
|
||||
|
||||
override def listDLCs(): Future[Vector[DLCStatus]] = {
|
||||
listDLCs(None)
|
||||
}
|
||||
|
||||
override def listDLCsByContact(
|
||||
contactId: InetSocketAddress): Future[Vector[DLCStatus]] = {
|
||||
listDLCs(Some(contactId))
|
||||
}
|
||||
|
||||
private def listDLCs(
|
||||
contactIdOpt: Option[InetSocketAddress]): Future[Vector[DLCStatus]] = {
|
||||
for {
|
||||
ids <- dlcDAO.findAll().map(_.map(_.dlcId))
|
||||
dlcs <- contactIdOpt match {
|
||||
case Some(contactId) =>
|
||||
dlcDAO.findByContactId(
|
||||
contactId.getHostString + ":" + contactId.getPort)
|
||||
case None => dlcDAO.findAll()
|
||||
}
|
||||
ids = dlcs.map(_.dlcId)
|
||||
dlcFs = ids.map(findDLC)
|
||||
dlcs <- Future.sequence(dlcFs)
|
||||
} yield {
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package org.bitcoins.dlc.wallet.internal
|
||||
|
||||
import org.bitcoins.core.api.dlc.wallet.db.{DLCContactDb, IncomingDLCOfferDb}
|
||||
import org.bitcoins.core.api.dlc.wallet.db.{
|
||||
DLCContactDb,
|
||||
DLCContactDbHelper,
|
||||
IncomingDLCOfferDb
|
||||
}
|
||||
import org.bitcoins.core.protocol.tlv.DLCOfferTLV
|
||||
import org.bitcoins.crypto.Sha256Digest
|
||||
import org.bitcoins.dlc.wallet.DLCWallet
|
||||
|
@ -13,13 +17,19 @@ trait IncomingDLCOffersHandling { self: DLCWallet =>
|
|||
|
||||
def registerIncomingDLCOffer(
|
||||
offerTLV: DLCOfferTLV,
|
||||
peer: Option[String],
|
||||
peerOpt: Option[String],
|
||||
message: Option[String]): Future[Sha256Digest] = {
|
||||
val dbo = IncomingDLCOfferDbHelper.fromTLV(offerTLV = offerTLV,
|
||||
peer = peer,
|
||||
peer = peerOpt,
|
||||
message = message)
|
||||
val contactDbOpt = peerOpt.map(DLCContactDbHelper.fromPeerAddress)
|
||||
for {
|
||||
added <- dlcWalletDAOs.incomingDLCOfferDAO.create(dbo)
|
||||
_ <- contactDbOpt match {
|
||||
case Some(contactDb) =>
|
||||
dlcWalletDAOs.contactDAO.createIfDoesNotExist(contactDb)
|
||||
case None => Future.successful(())
|
||||
}
|
||||
_ <- dlcConfig.walletCallbacks.executeOnDLCOfferAdd(logger, added)
|
||||
} yield dbo.hash
|
||||
}
|
||||
|
@ -58,4 +68,14 @@ trait IncomingDLCOffersHandling { self: DLCWallet =>
|
|||
override def findDLCContacts(alias: String): Future[Vector[DLCContactDb]] =
|
||||
contactDAO.findByAlias(alias)
|
||||
|
||||
override def addDLCContactMapping(
|
||||
dlcId: Sha256Digest,
|
||||
contcatId: InetSocketAddress): Future[Unit] = {
|
||||
dlcDAO
|
||||
.updateDLCContactMapping(dlcId, contcatId)
|
||||
}
|
||||
|
||||
override def removeDLCContactMapping(dlcId: Sha256Digest): Future[Unit] = {
|
||||
dlcDAO.deleteDLCContactMapping(dlcId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,23 @@ case class DLCContactDAO()(implicit
|
|||
ts: Vector[DLCContactDb]): Future[Vector[DLCContactDb]] =
|
||||
createAllNoAutoInc(ts, safeDatabase)
|
||||
|
||||
def createIfDoesNotExist(contact: DLCContactDb): Future[DLCContactDb] = {
|
||||
val action = for {
|
||||
foundOpt <- table
|
||||
.filter(_.address === contact.address)
|
||||
.result
|
||||
.headOption
|
||||
result <-
|
||||
foundOpt match {
|
||||
case Some(found) => DBIO.successful(found)
|
||||
case None =>
|
||||
(table += contact).map(_ => contact)
|
||||
}
|
||||
} yield result
|
||||
|
||||
safeDatabase.run(action)
|
||||
}
|
||||
|
||||
override protected def findByPrimaryKeys(ids: Vector[
|
||||
InetSocketAddress]): Query[DLCContactTable, DLCContactDb, Seq] =
|
||||
table.filter(_.address.inSet(ids)).sortBy(_.alias)
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.bitcoins.dlc.wallet.DLCAppConfig
|
|||
import scodec.bits.ByteVector
|
||||
import slick.lifted._
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import java.sql.SQLException
|
||||
import java.time.Instant
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
|
||||
|
@ -28,6 +30,9 @@ case class DLCDAO()(implicit
|
|||
|
||||
override val table: TableQuery[DLCTable] = TableQuery[DLCTable]
|
||||
|
||||
private lazy val contactTable: slick.lifted.TableQuery[
|
||||
DLCContactDAO#DLCContactTable] = DLCContactDAO().table
|
||||
|
||||
override def createAll(ts: Vector[DLCDb]): Future[Vector[DLCDb]] =
|
||||
createAllNoAutoInc(ts, safeDatabase)
|
||||
|
||||
|
@ -118,6 +123,49 @@ case class DLCDAO()(implicit
|
|||
safeDatabase.runVec(q.result)
|
||||
}
|
||||
|
||||
def findByContactId(contactId: String): Future[Vector[DLCDb]] = {
|
||||
val peer: Option[String] = Some(contactId)
|
||||
val action = table.filter(_.peerOpt === peer).result
|
||||
safeDatabase.runVec(action)
|
||||
}
|
||||
|
||||
def updateDLCContactMapping(
|
||||
dlcId: Sha256Digest,
|
||||
contcatId: InetSocketAddress): Future[Unit] = {
|
||||
val contactQuery = contactTable.filter(_.address === contcatId)
|
||||
|
||||
val action = for {
|
||||
contactExists <- contactQuery.exists.result
|
||||
_ <-
|
||||
if (contactExists) DBIO.successful(())
|
||||
else DBIO.failed(new SQLException(s"Unknown contact: $contcatId"))
|
||||
res <- updatePeerAction(
|
||||
dlcId,
|
||||
Some(contcatId.getHostName + ":" + contcatId.getPort))
|
||||
} yield res
|
||||
|
||||
safeDatabase.run(action).map(_ => ())
|
||||
}
|
||||
|
||||
def deleteDLCContactMapping(dlcId: Sha256Digest): Future[Unit] = {
|
||||
val action = updatePeerAction(dlcId, None)
|
||||
|
||||
safeDatabase.run(action).map(_ => ())
|
||||
}
|
||||
|
||||
private def updatePeerAction(dlcId: Sha256Digest, peerOpt: Option[String]) = {
|
||||
val dlcQuery = table.filter(_.dlcId === dlcId)
|
||||
|
||||
for {
|
||||
dlcOpt <- dlcQuery.result.headOption
|
||||
res <- dlcOpt match {
|
||||
case None => DBIO.failed(new SQLException(s"Unknown DLC: $dlcId"))
|
||||
case Some(dlc) =>
|
||||
dlcQuery.update(dlc.copy(peerOpt = peerOpt))
|
||||
}
|
||||
} yield res
|
||||
}
|
||||
|
||||
class DLCTable(tag: Tag)
|
||||
extends Table[DLCDb](tag, schemaName, "global_dlc_data") {
|
||||
|
||||
|
@ -162,6 +210,8 @@ case class DLCDAO()(implicit
|
|||
def serializationVersion: Rep[DLCSerializationVersion] = column(
|
||||
"serialization_version")
|
||||
|
||||
def peerOpt: Rep[Option[String]] = column("peer")
|
||||
|
||||
override def * : ProvenShape[DLCDb] =
|
||||
(dlcId,
|
||||
tempContractId,
|
||||
|
@ -179,6 +229,7 @@ case class DLCDAO()(implicit
|
|||
fundingTxIdOpt,
|
||||
closingTxIdOpt,
|
||||
aggregateSignatureOpt,
|
||||
serializationVersion).<>(DLCDb.tupled, DLCDb.unapply)
|
||||
serializationVersion,
|
||||
peerOpt).<>(DLCDb.tupled, DLCDb.unapply)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,8 @@ object DLCAcceptUtil extends Logging {
|
|||
account: AccountDb,
|
||||
chainType: HDChainType,
|
||||
nextIndex: Int,
|
||||
contractInfo: ContractInfo): DLCDb = {
|
||||
contractInfo: ContractInfo,
|
||||
peerOpt: Option[String]): DLCDb = {
|
||||
DLCDb(
|
||||
dlcId = dlcId,
|
||||
tempContractId = offer.tempContractId,
|
||||
|
@ -133,7 +134,8 @@ object DLCAcceptUtil extends Logging {
|
|||
fundingTxIdOpt = None,
|
||||
closingTxIdOpt = None,
|
||||
aggregateSignatureOpt = None,
|
||||
serializationVersion = contractInfo.serializationVersion
|
||||
serializationVersion = contractInfo.serializationVersion,
|
||||
peerOpt = peerOpt
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ object DLCStatusBuilder {
|
|||
dlcDb.feeRate,
|
||||
totalCollateral,
|
||||
localCollateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.AcceptComputingAdaptorSigs =>
|
||||
AcceptedComputingAdaptorSigs(
|
||||
|
@ -59,7 +60,8 @@ object DLCStatusBuilder {
|
|||
feeRate = dlcDb.feeRate,
|
||||
totalCollateral = totalCollateral,
|
||||
localCollateral = localCollateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.Accepted =>
|
||||
Accepted(
|
||||
|
@ -73,7 +75,8 @@ object DLCStatusBuilder {
|
|||
dlcDb.feeRate,
|
||||
totalCollateral,
|
||||
localCollateral,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.SignComputingAdaptorSigs =>
|
||||
SignedComputingAdaptorSigs(
|
||||
|
@ -88,7 +91,8 @@ object DLCStatusBuilder {
|
|||
totalCollateral = totalCollateral,
|
||||
localCollateral = localCollateral,
|
||||
dlcDb.fundingTxIdOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.Signed =>
|
||||
Signed(
|
||||
|
@ -103,7 +107,8 @@ object DLCStatusBuilder {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
dlcDb.fundingTxIdOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.Broadcasted =>
|
||||
Broadcasted(
|
||||
|
@ -118,7 +123,8 @@ object DLCStatusBuilder {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
dlcDb.fundingTxIdOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.Confirmed =>
|
||||
Confirmed(
|
||||
|
@ -133,7 +139,8 @@ object DLCStatusBuilder {
|
|||
totalCollateral,
|
||||
localCollateral,
|
||||
dlcDb.fundingTxIdOpt.get,
|
||||
payoutAddress
|
||||
payoutAddress,
|
||||
dlcDb.peerOpt
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -186,7 +193,8 @@ object DLCStatusBuilder {
|
|||
closingTx.txIdBE,
|
||||
myPayout = accounting.myPayout,
|
||||
counterPartyPayout = accounting.theirPayout,
|
||||
payoutAddress = payoutAddress
|
||||
payoutAddress = payoutAddress,
|
||||
peer = dlcDb.peerOpt
|
||||
)
|
||||
refund
|
||||
case oracleOutcomeState: DLCState.ClosedViaOracleOutcomeState =>
|
||||
|
@ -214,7 +222,8 @@ object DLCStatusBuilder {
|
|||
oracleOutcome,
|
||||
myPayout = accounting.myPayout,
|
||||
counterPartyPayout = accounting.theirPayout,
|
||||
payoutAddress = payoutAddress
|
||||
payoutAddress = payoutAddress,
|
||||
peer = dlcDb.peerOpt
|
||||
)
|
||||
case DLCState.RemoteClaimed =>
|
||||
RemoteClaimed(
|
||||
|
@ -234,7 +243,8 @@ object DLCStatusBuilder {
|
|||
oracleOutcome,
|
||||
myPayout = accounting.myPayout,
|
||||
counterPartyPayout = accounting.theirPayout,
|
||||
payoutAddress = payoutAddress
|
||||
payoutAddress = payoutAddress,
|
||||
peer = dlcDb.peerOpt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,12 +262,14 @@ the `-p 9999:9999` port mapping on the docker container to adjust for this.
|
|||
- `collateral` - Satoshis to fund your side of the DLC
|
||||
- `feerate` - Fee rate for both funding and closing transactions, in sats/vbytes
|
||||
- `refundlocktime` - Locktime of the refund transaction
|
||||
- `--cetlocktime <value>` - Should not be set unless you know what you are doing. Locktime of the contract execution transactions (defaults to current height)
|
||||
- `cetlocktime <value>` - Should not be set unless you know what you are doing. Locktime of the contract execution transactions (defaults to current height)
|
||||
- `peer` - Peer's network address
|
||||
- `acceptdlc` `offer` `peer` - Accepts a DLC offer given from another party
|
||||
- `offer` - Hex encoded dlc offer message
|
||||
- `peer` - Peer's network address
|
||||
- `acceptdlcoffer` `offer` - Accepts a DLC offer given from another party
|
||||
- `offer` - Hex encoded offer message
|
||||
- `peer` - Peer's network address
|
||||
- `acceptdlcofferfromfile` `path` `[destination]` - Accepts a DLC offer given from another party
|
||||
- `path` - Path to dlc offer file
|
||||
- `destination` - Path to write dlc accept message
|
||||
|
@ -278,6 +280,9 @@ the `-p 9999:9999` port mapping on the docker container to adjust for this.
|
|||
- `contacts-list` - lists all contacts in the wallet
|
||||
- `contact-remove` `address`
|
||||
- `address` - the tor address for the peer to remove
|
||||
- `dlc-contact-add` `dlcid` `address` - Associated a DLC with a peer
|
||||
- `dlc-contact-remove` `dlcid` - Removes a DLC-peer association
|
||||
- `address` - the tor address for the peer to remove
|
||||
- `signdlc` `accept` - Signs a DLC
|
||||
- `accept` - Hex encoded dlc accept message
|
||||
- `signdlcfromfile` `path` `[destination]` - Signs a DLC
|
||||
|
@ -305,6 +310,7 @@ the `-p 9999:9999` port mapping on the docker container to adjust for this.
|
|||
- `canceldlc` `dlcId` - Cancels a DLC and unreserves used utxos
|
||||
- `dlcId` - Internal id of the DLC
|
||||
- `getdlcs` - Returns all dlcs in the wallet
|
||||
- `address` - optional contact address, if specified the RPC returns only DLCs associated with the given address
|
||||
- `getdlc` `dlcId` - Gets a specific dlc in the wallet
|
||||
- `dlcId` - Internal id of the DLC
|
||||
- `offer-add` `offerTLV` `peerAddress` `message` - Puts an incoming offer into the inbox
|
||||
|
|
|
@ -21,7 +21,8 @@ case class DLCDAOs(
|
|||
dlcSigsDAO: DLCCETSignaturesDAO,
|
||||
dlcRefundSigDAO: DLCRefundSigsDAO,
|
||||
dlcRemoteTxDAO: DLCRemoteTxDAO,
|
||||
incomingDLCOfferDAO: IncomingDLCOfferDAO) {
|
||||
incomingDLCOfferDAO: IncomingDLCOfferDAO,
|
||||
contactDAO: DLCContactDAO) {
|
||||
|
||||
val list = Vector(
|
||||
announcementDAO,
|
||||
|
@ -35,7 +36,8 @@ case class DLCDAOs(
|
|||
dlcSigsDAO,
|
||||
dlcRefundSigDAO,
|
||||
dlcRemoteTxDAO,
|
||||
incomingDLCOfferDAO
|
||||
incomingDLCOfferDAO,
|
||||
contactDAO: DLCContactDAO
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -54,6 +56,7 @@ trait DLCDAOFixture extends BitcoinSFixture with EmbeddedPg {
|
|||
val dlcRefundSigDAO = DLCRefundSigsDAO()
|
||||
val dlcRemoteTxDAO = DLCRemoteTxDAO()
|
||||
val incomingDLCOfferDAO = IncomingDLCOfferDAO()
|
||||
val contactDAO = DLCContactDAO()
|
||||
DLCDAOs(
|
||||
announcementDAO = announcementDAO,
|
||||
nonceDAO = nonceDAO,
|
||||
|
@ -66,7 +69,8 @@ trait DLCDAOFixture extends BitcoinSFixture with EmbeddedPg {
|
|||
dlcSigsDAO = dlcSigsDAO,
|
||||
dlcRefundSigDAO = dlcRefundSigDAO,
|
||||
dlcRemoteTxDAO = dlcRemoteTxDAO,
|
||||
incomingDLCOfferDAO = incomingDLCOfferDAO
|
||||
incomingDLCOfferDAO = incomingDLCOfferDAO,
|
||||
contactDAO = contactDAO
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,8 @@ object DLCWalletUtil extends Logging {
|
|||
fundingTxIdOpt = None,
|
||||
closingTxIdOpt = None,
|
||||
aggregateSignatureOpt = None,
|
||||
serializationVersion = DLCSerializationVersion.current
|
||||
serializationVersion = DLCSerializationVersion.current,
|
||||
peerOpt = None
|
||||
)
|
||||
|
||||
lazy val sampleContractDataDb: DLCContractDataDb = DLCContractDataDb(
|
||||
|
@ -310,10 +311,12 @@ object DLCWalletUtil extends Logging {
|
|||
feeRateOpt = Some(SatoshisPerVirtualByte.fromLong(10)),
|
||||
locktime = dummyTimeouts.contractMaturity.toUInt32,
|
||||
refundLocktime = dummyTimeouts.contractTimeout.toUInt32,
|
||||
peerAddressOpt = None,
|
||||
externalPayoutAddressOpt = payoutAddressAOpt,
|
||||
externalChangeAddressOpt = changeAddressAOpt
|
||||
)
|
||||
accept <- walletB.acceptDLCOffer(offer,
|
||||
None,
|
||||
payoutAddressBOpt,
|
||||
changeAddressBOpt)
|
||||
sigs <- walletA.signDLC(accept)
|
||||
|
|
Loading…
Add table
Reference in a new issue