From 525fb2ac0dab126bbb428e2fe1470462fa244ac8 Mon Sep 17 00:00:00 2001 From: Nadav Kohen Date: Mon, 25 Apr 2022 14:30:32 -0500 Subject: [PATCH] Default createDLCOffer to current block height (#4285) * Added createDLCOffer endpoint which doesn't take a locktime and uses current block height instead * Made cetLocktime an option instead of an argument to the CLI, updated docs * fix compile Co-authored-by: Chris Stewart --- .../scala/org/bitcoins/cli/ConsoleCli.scala | 30 ++++++++-------- .../gui/dlc/dialog/CreateDLCOfferDialog.scala | 4 +-- .../bitcoins/server/ServerJsonModels.scala | 7 ++-- .../org/bitcoins/server/WalletRoutes.scala | 36 ++++++++++++------- .../core/api/dlc/wallet/DLCWalletApi.scala | 24 +++++++++++++ .../org/bitcoins/dlc/wallet/DLCWallet.scala | 18 ++++++++++ docs/applications/server.md | 4 +-- docs/wallet/wallet-election-example.md | 6 ++-- docs/wallet/wallet-price-example.md | 6 ++-- 9 files changed, 93 insertions(+), 42 deletions(-) diff --git a/app/cli/src/main/scala/org/bitcoins/cli/ConsoleCli.scala b/app/cli/src/main/scala/org/bitcoins/cli/ConsoleCli.scala index 72c77a822b..2131ba1dd1 100644 --- a/app/cli/src/main/scala/org/bitcoins/cli/ConsoleCli.scala +++ b/app/cli/src/main/scala/org/bitcoins/cli/ConsoleCli.scala @@ -836,7 +836,7 @@ object ConsoleCli { Satoshis.zero, None, UInt32.zero, - UInt32.zero))) + None))) .text("Creates a DLC offer that another party can accept") .children( arg[ContractInfoV0TLV]("contractInfo") @@ -866,15 +866,6 @@ object ConsoleCli { offer.copy(feeRateOpt = Some(feeRate)) case other => other })), - arg[UInt32]("locktime") - .text("Locktime of the contract execution transactions") - .required() - .action((locktime, conf) => - conf.copy(command = conf.command match { - case offer: CreateDLCOffer => - offer.copy(locktime = locktime) - case other => other - })), arg[UInt32]("refundlocktime") .text("Locktime of the refund transaction") .required() @@ -883,6 +874,15 @@ object ConsoleCli { case offer: CreateDLCOffer => offer.copy(refundLT = refundLT) case other => other + })), + opt[UInt32]("cetlocktime") + .text("Locktime of the contract execution transactions") + .optional() + .action((locktime, conf) => + conf.copy(command = conf.command match { + case offer: CreateDLCOffer => + offer.copy(cetLocktimeOpt = Some(locktime)) + case other => other })) ), cmd("acceptdlc") @@ -1884,15 +1884,15 @@ object ConsoleCli { case CreateDLCOffer(contractInfo, collateral, feeRateOpt, - locktime, - refundLT) => + refundLT, + cetLocktimeOpt) => RequestParam( "createdlcoffer", Seq( up.writeJs(contractInfo), up.writeJs(collateral), up.writeJs(feeRateOpt), - up.writeJs(locktime), + up.writeJs(cetLocktimeOpt), up.writeJs(refundLT) ) ) @@ -2299,8 +2299,8 @@ object CliCommand { contractInfo: ContractInfoV0TLV, collateral: Satoshis, feeRateOpt: Option[SatoshisPerVirtualByte], - locktime: UInt32, - refundLT: UInt32) + refundLT: UInt32, + cetLocktimeOpt: Option[UInt32]) extends AppServerCliCommand sealed trait AcceptDLCCliCommand extends AppServerCliCommand diff --git a/app/gui/src/main/scala/org/bitcoins/gui/dlc/dialog/CreateDLCOfferDialog.scala b/app/gui/src/main/scala/org/bitcoins/gui/dlc/dialog/CreateDLCOfferDialog.scala index d32451a301..303cc94a60 100644 --- a/app/gui/src/main/scala/org/bitcoins/gui/dlc/dialog/CreateDLCOfferDialog.scala +++ b/app/gui/src/main/scala/org/bitcoins/gui/dlc/dialog/CreateDLCOfferDialog.scala @@ -609,8 +609,8 @@ class CreateDLCOfferDialog(feeRate: FeeUnit) contractInfo = contractInfo, collateral = collateral, feeRateOpt = feeRateOpt, - locktime = UInt32.zero, - refundLT = refundLocktime + refundLT = refundLocktime, + cetLocktimeOpt = None ) } } diff --git a/app/server/src/main/scala/org/bitcoins/server/ServerJsonModels.scala b/app/server/src/main/scala/org/bitcoins/server/ServerJsonModels.scala index 9252ec4db6..0ffa92de69 100644 --- a/app/server/src/main/scala/org/bitcoins/server/ServerJsonModels.scala +++ b/app/server/src/main/scala/org/bitcoins/server/ServerJsonModels.scala @@ -675,7 +675,7 @@ case class CreateDLCOffer( contractInfoTLV: ContractInfoV0TLV, collateral: Satoshis, feeRateOpt: Option[SatoshisPerVirtualByte], - locktime: UInt32, + locktimeOpt: Option[UInt32], refundLocktime: UInt32, externalPayoutAddressOpt: Option[BitcoinAddress], externalChangeAddressOpt: Option[BitcoinAddress]) @@ -695,7 +695,8 @@ object CreateDLCOffer extends ServerJsonModels { val contractInfoTLV = jsToContractInfoTLV(contractInfoJs) val collateral = jsToSatoshis(collateralJs) val feeRate = jsToSatoshisPerVirtualByteOpt(feeRateOptJs) - val locktime = jsToUInt32(locktimeJs) + val locktimeJsOpt = nullToOpt(locktimeJs) + val locktimeOpt = locktimeJsOpt.map(js => jsToUInt32(js)) val refundLT = jsToUInt32(refundLTJs) val payoutAddressJsOpt = nullToOpt(payoutAddressJs) val payoutAddressOpt = @@ -706,7 +707,7 @@ object CreateDLCOffer extends ServerJsonModels { CreateDLCOffer(contractInfoTLV, collateral, feeRate, - locktime, + locktimeOpt, refundLT, payoutAddressOpt, changeAddressOpt) diff --git a/app/server/src/main/scala/org/bitcoins/server/WalletRoutes.scala b/app/server/src/main/scala/org/bitcoins/server/WalletRoutes.scala index c98d5bfff5..84cffa008f 100644 --- a/app/server/src/main/scala/org/bitcoins/server/WalletRoutes.scala +++ b/app/server/src/main/scala/org/bitcoins/server/WalletRoutes.scala @@ -341,7 +341,7 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit CreateDLCOffer(contractInfo, collateral, feeRateOpt, - locktime, + locktimeOpt, refundLT, payoutAddressOpt, changeAddressOpt)) => @@ -357,17 +357,29 @@ case class WalletRoutes(wallet: AnyDLCHDWalletApi)(implicit .map(_.hex)}") } - wallet - .createDLCOffer(contractInfo, - collateral, - feeRateOpt, - locktime, - refundLT, - payoutAddressOpt, - changeAddressOpt) - .map { offer => - Server.httpSuccess(offer.toMessage.hex) - } + val offerF = locktimeOpt match { + case Some(locktime) => + wallet + .createDLCOffer(contractInfo, + collateral, + feeRateOpt, + locktime, + refundLT, + payoutAddressOpt, + changeAddressOpt) + case None => + wallet + .createDLCOffer(contractInfo, + collateral, + feeRateOpt, + refundLT, + payoutAddressOpt, + changeAddressOpt) + } + + offerF.map { offer => + Server.httpSuccess(offer.toMessage.hex) + } } } diff --git a/core/src/main/scala/org/bitcoins/core/api/dlc/wallet/DLCWalletApi.scala b/core/src/main/scala/org/bitcoins/core/api/dlc/wallet/DLCWalletApi.scala index ac676073db..7fba7f4df8 100644 --- a/core/src/main/scala/org/bitcoins/core/api/dlc/wallet/DLCWalletApi.scala +++ b/core/src/main/scala/org/bitcoins/core/api/dlc/wallet/DLCWalletApi.scala @@ -23,6 +23,22 @@ import scala.concurrent._ trait DLCWalletApi { self: WalletApi => + def createDLCOffer( + contractInfoTLV: ContractInfoTLV, + collateral: Satoshis, + feeRateOpt: Option[SatoshisPerVirtualByte], + refundLT: UInt32, + externalPayoutAddressOpt: Option[BitcoinAddress], + externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] = { + val contractInfo = ContractInfo.fromTLV(contractInfoTLV) + createDLCOffer(contractInfo, + collateral, + feeRateOpt, + refundLT, + externalPayoutAddressOpt, + externalChangeAddressOpt) + } + def createDLCOffer( contractInfoTLV: ContractInfoTLV, collateral: Satoshis, @@ -41,6 +57,14 @@ trait DLCWalletApi { self: WalletApi => externalChangeAddressOpt) } + def createDLCOffer( + contractInfo: ContractInfo, + collateral: Satoshis, + feeRateOpt: Option[SatoshisPerVirtualByte], + refundLT: UInt32, + externalPayoutAddressOpt: Option[BitcoinAddress], + externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] + def createDLCOffer( contractInfo: ContractInfo, collateral: Satoshis, diff --git a/dlc-wallet/src/main/scala/org/bitcoins/dlc/wallet/DLCWallet.scala b/dlc-wallet/src/main/scala/org/bitcoins/dlc/wallet/DLCWallet.scala index 766cdb537a..e0822234b1 100644 --- a/dlc-wallet/src/main/scala/org/bitcoins/dlc/wallet/DLCWallet.scala +++ b/dlc-wallet/src/main/scala/org/bitcoins/dlc/wallet/DLCWallet.scala @@ -268,6 +268,24 @@ abstract class DLCWallet } yield () } + override def createDLCOffer( + contractInfo: ContractInfo, + collateral: Satoshis, + feeRateOpt: Option[SatoshisPerVirtualByte], + refundLT: UInt32, + externalPayoutAddressOpt: Option[BitcoinAddress], + externalChangeAddressOpt: Option[BitcoinAddress]): Future[DLCOffer] = { + chainQueryApi.getBestHashBlockHeight().flatMap { height => + createDLCOffer(contractInfo, + collateral, + feeRateOpt, + locktime = UInt32(height), + refundLT, + externalPayoutAddressOpt, + externalChangeAddressOpt) + } + } + /** Creates a DLCOffer, if one has already been created * with the given parameters then that one will be returned instead. * diff --git a/docs/applications/server.md b/docs/applications/server.md index a1dc3cf387..9065dbf180 100644 --- a/docs/applications/server.md +++ b/docs/applications/server.md @@ -257,12 +257,12 @@ the `-p 9999:9999` port mapping on the docker container to adjust for this. - `decodeattestments` `attestments` - Decodes an oracle attestments message into json - `attestments` - Hex encoded oracle attestments message - `getdlchostaddress` - Returns the public listening address of the DLC Node - - `createdlcoffer` `contractInfo` `collateral` `[feerate]` `locktime` `refundlocktime` - Creates a DLC offer that another party can accept + - `createdlcoffer` `contractInfo` `collateral` `[feerate]` `refundlocktime` `[options]` - Creates a DLC offer that another party can accept - `contractInfo` - Hex encoded contractInfo message - `collateral` - Satoshis to fund your side of the DLC - `feerate` - Fee rate for both funding and closing transactions, in sats/vbytes - - `locktime` - Locktime of the contract execution transactions - `refundlocktime` - Locktime of the refund transaction + - `--cetlocktime ` - Should not be set unless you know what you are doing. Locktime of the contract execution transactions (defaults to current height) - `acceptdlc` `offer` `peer` - Accepts a DLC offer given from another party - `offer` - Hex encoded dlc offer message - `peer` - Peer's network address diff --git a/docs/wallet/wallet-election-example.md b/docs/wallet/wallet-election-example.md index 2b664a1258..624eb403e6 100644 --- a/docs/wallet/wallet-election-example.md +++ b/docs/wallet/wallet-election-example.md @@ -144,11 +144,10 @@ You can create the offer with the `createdlcoffer`. As arguments this rpc takes 1. contract info (what we build last step) 2. your collateral (the amount of money YOU are putting in the DLC) 3. fee rate (sats/vbyte) -4. locktime -5. refund locktime +4. refund locktime As of this writing, the current block height is `703,401`. For the sake of this example -I'm going to pick a `locktime=0` and a refund locktime 2 weeks in advance `refundLocktime=705417` +I'm going to pick a refund locktime 2 weeks in advance `refundLocktime=705417` Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral. @@ -156,7 +155,6 @@ Note: this RPC will fail if you don't have enough funds in your wallet to fund y ./bitcoin-s-cli createdlcoffer fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e \ 60000 \ 1 \ -0 \ 705417 a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389 ``` diff --git a/docs/wallet/wallet-price-example.md b/docs/wallet/wallet-price-example.md index 0a94cd2ca3..b2766a7c00 100644 --- a/docs/wallet/wallet-price-example.md +++ b/docs/wallet/wallet-price-example.md @@ -206,11 +206,10 @@ You can create the offer with the `createdlcoffer`. As arguments this rpc takes 1. contract info (what we build last step) 2. your collateral (the amount of money YOU are putting in the DLC) 3. fee rate (sats/vbyte) -4. locktime -5. refund locktime +4. refund locktime As of this writing, the current block height is `705161` . For the sake of this example -I'm going to pick a `locktime=0` and a refund locktime 2 weeks in advance `refundLocktime=707177` +I'm going to pick a refund locktime 2 weeks in advance `refundLocktime=707177` Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral. @@ -218,7 +217,6 @@ Note: this RPC will fail if you don't have enough funds in your wallet to fund y ./bitcoin-s-cli createdlcoffer fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \ 50000 \ 1 \ -0 \ > 707177 \ a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69 ```