From c5c76ea46bbc013e68e0dbbac932fc199537df33 Mon Sep 17 00:00:00 2001 From: Chris Stewart Date: Mon, 25 Oct 2021 08:16:23 -0500 Subject: [PATCH] Add missing markdown files (#3779) --- .../version-1.8.0/chain/chain-query-api.md | 171 ++++++++ .../version-1.8.0/chain/chain.md | 77 ++++ .../version-1.8.0/node/node-api.md | 83 ++++ .../oracle/oracle-election-example.md | 113 +++++ .../oracle/oracle-price-example.md | 264 ++++++++++++ .../version-1.8.0/oracle/oracle-server.md | 195 +++++++++ .../version-1.8.0/rpc/bitcoind.md | 133 ++++++ .../version-1.8.0/testkit/testkit.md | 173 ++++++++ .../version-1.8.0/wallet/dlc.md | 322 ++++++++++++++ .../wallet/wallet-election-example.md | 319 ++++++++++++++ .../wallet/wallet-price-example.md | 406 ++++++++++++++++++ .../version-1.8.0/wallet/wallet.md | 138 ++++++ 12 files changed, 2394 insertions(+) create mode 100644 website/versioned_docs/version-1.8.0/chain/chain-query-api.md create mode 100644 website/versioned_docs/version-1.8.0/chain/chain.md create mode 100644 website/versioned_docs/version-1.8.0/node/node-api.md create mode 100644 website/versioned_docs/version-1.8.0/oracle/oracle-election-example.md create mode 100644 website/versioned_docs/version-1.8.0/oracle/oracle-price-example.md create mode 100644 website/versioned_docs/version-1.8.0/oracle/oracle-server.md create mode 100644 website/versioned_docs/version-1.8.0/rpc/bitcoind.md create mode 100644 website/versioned_docs/version-1.8.0/testkit/testkit.md create mode 100644 website/versioned_docs/version-1.8.0/wallet/dlc.md create mode 100644 website/versioned_docs/version-1.8.0/wallet/wallet-election-example.md create mode 100644 website/versioned_docs/version-1.8.0/wallet/wallet-price-example.md create mode 100644 website/versioned_docs/version-1.8.0/wallet/wallet.md diff --git a/website/versioned_docs/version-1.8.0/chain/chain-query-api.md b/website/versioned_docs/version-1.8.0/chain/chain-query-api.md new file mode 100644 index 0000000000..0a12758d3d --- /dev/null +++ b/website/versioned_docs/version-1.8.0/chain/chain-query-api.md @@ -0,0 +1,171 @@ +--- +id: version-1.8.0-chain-query-api +title: Chain Query API +original_id: chain-query-api +--- + + +### ChainQueryAPI + +The ChainQueryApi is how the wallet project stays aware of the current best chain. +This allows the wallet for example to calculate the number of confirmations for a transaction, +get the current chain tip, or even retrieve block filters for a given set of blocks. + +Since this is an API it can be hooked up to the `chain` module of bitcoin-s but it can also be linked to +any other implementation of your choosing. This allows you to use the bitcoin-s wallet in any schema that you +want. + +The functions that the ChainQueryApi supports are: + +```scala +trait ChainQueryApi { + + /** Gets the height of the given block */ + def getBlockHeight(blockHash: DoubleSha256DigestBE): Future[Option[Int]] + + /** Gets the hash of the block that is what we consider "best" */ + def getBestBlockHash(): Future[DoubleSha256DigestBE] + + /** Gets number of confirmations for the given block hash*/ + def getNumberOfConfirmations( + blockHashOpt: DoubleSha256DigestBE): Future[Option[Int]] + + /** Gets the number of compact filters in the database */ + def getFilterCount: Future[Int] + + /** Returns the block height of the given block stamp */ + def getHeightByBlockStamp(blockStamp: BlockStamp): Future[Int] + + def getFiltersBetweenHeights( + startHeight: Int, + endHeight: Int): Future[Vector[FilterResponse]] +} +``` + +## Chain query with bitcoind + +As an example, we will show you how to use the `ChainQueryApi` and bitcoind to query chain data. + +```scala +implicit val system: ActorSystem = ActorSystem(s"node-api-example") +implicit val ec: ExecutionContextExecutor = system.dispatcher +implicit val walletConf: WalletAppConfig = + BitcoinSTestAppConfig.getSpvTestConfig().walletConf + +// let's use a helper method to get a v19 bitcoind +// and a ChainApi +val instance = BitcoindInstanceLocal.fromConfigFile(BitcoindConfig.DEFAULT_CONF_FILE) +val bitcoind = BitcoindV19RpcClient(instance) +val nodeApi = BitcoinSWalletTest.MockNodeApi + +// This function can be used to create a callback for when our chain api receives a transaction, block, or +// a block filter, the returned NodeCallbacks will contain the necessary items to initialize the callbacks +def createCallbacks( + processTransaction: Transaction => Future[Unit], + processCompactFilters: (Vector[(DoubleSha256Digest, GolombFilter)]) => Future[Unit], + processBlock: Block => Future[Unit]): NodeCallbacks = { + lazy val onTx: OnTxReceived = { tx => + processTransaction(tx) + } + lazy val onCompactFilters: OnCompactFiltersReceived = { + blockFilters => + processCompactFilters(blockFilters) + } + lazy val onBlock: OnBlockReceived = { block => + processBlock(block) + } + NodeCallbacks(onTxReceived = Vector(onTx), + onBlockReceived = Vector(onBlock), + onCompactFiltersReceived = Vector(onCompactFilters)) + } + +// Here is a super simple example of a callback, this could be replaced with anything, from +// relaying the block on the network, finding relevant wallet transactions, verifying the block, +// or writing it to disk +val exampleProcessTx = (tx: Transaction) => + Future.successful(println(s"Received tx: ${tx.txIdBE}")) + +val exampleProcessBlock = (block: Block) => + Future.successful(println(s"Received block: ${block.blockHeader.hashBE}")) + +val exampleProcessFilters = + (filters: Vector[(DoubleSha256Digest, GolombFilter)]) => + Future.successful(println(s"Received filter: ${filters.head._1.flip.hex} ${filters.head._2.hash.flip.hex}")) + +val exampleCallbacks = + createCallbacks(exampleProcessTx, exampleProcessFilters, exampleProcessBlock) + +// Here is where we are defining our actual chain api, Ideally this could be it's own class +// but for the examples sake we will keep it small. +val chainApi = new ChainQueryApi { + + override def epochSecondToBlockHeight(time: Long): Future[Int] = + Future.successful(0) + + /** Gets the height of the given block */ + override def getBlockHeight( + blockHash: DoubleSha256DigestBE): Future[Option[Int]] = { + bitcoind.getBlock(blockHash).map(block => Some(block.height)) + } + + /** Gets the hash of the block that is what we consider "best" */ + override def getBestBlockHash(): Future[DoubleSha256DigestBE] = { + bitcoind.getBestBlockHash + } + + /** Gets number of confirmations for the given block hash */ + override def getNumberOfConfirmations( + blockHash: DoubleSha256DigestBE): Future[Option[Int]] = { + for { + tip <- bitcoind.getBlockCount + block <- bitcoind.getBlock(blockHash) + } yield { + Some(tip - block.height + 1) + } + } + + /** Gets the number of compact filters in the database */ + override def getFilterCount(): Future[Int] = { + // since bitcoind should have the filter for + // every block we can just return the block height + bitcoind.getBlockCount + } + + /** Returns the block height of the given block stamp */ + override def getHeightByBlockStamp(blockStamp: BlockStamp): Future[Int] = { + blockStamp match { + case blockHeight: BlockStamp.BlockHeight => + Future.successful(blockHeight.height) + case blockHash: BlockStamp.BlockHash => + getBlockHeight(blockHash.hash).map(_.get) + case blockTime: BlockStamp.BlockTime => + Future.failed(new RuntimeException(s"Not implemented: $blockTime")) + } + } + + override def getFiltersBetweenHeights( + startHeight: Int, + endHeight: Int): Future[Vector[FilterResponse]] = { + val filterFs = startHeight + .until(endHeight) + .map { height => + for { + hash <- bitcoind.getBlockHash(height) + filter <- bitcoind.getBlockFilter(hash, FilterType.Basic) + } yield { + FilterResponse(filter.filter, hash, height) + } + } + .toVector + + Future.sequence(filterFs) + } + } + +// Finally, we can initialize our wallet with our own node api +val wallet = + Wallet(nodeApi = nodeApi, chainQueryApi = chainApi, feeRateApi = ConstantFeeRateProvider(SatoshisPerVirtualByte.one)) + +// Then to trigger one of the events we can run +wallet.chainQueryApi.getFiltersBetweenHeights(100, 150) +``` diff --git a/website/versioned_docs/version-1.8.0/chain/chain.md b/website/versioned_docs/version-1.8.0/chain/chain.md new file mode 100644 index 0000000000..d6bdcb861d --- /dev/null +++ b/website/versioned_docs/version-1.8.0/chain/chain.md @@ -0,0 +1,77 @@ +--- +title: Blockchain Verification +id: version-1.8.0-chain +original_id: chain +--- + +Bitcoin-S comes bundled with a rudimentary blockchain verification +module. This module is currently only released as a library, and not as a binary. +This is because it (nor the documentation) is not deemed production +ready. Use at your own risk, and without too much money depending on it. + +## Syncing and verifying block headers + +Using the `chain` module of Bitcoin-S it's possible to +sync and verify block headers from the Bitcoin blockchain. In this document +we demonstrate how to do this, while persisting it to disk. We should be +able to read this chain on subsequent runs, assuming we are connected +to the same `bitcoind` instance. + + +```scala +implicit val ec = ExecutionContext.global +implicit val system = ActorSystem("System") +// We are assuming that a `bitcoind` regtest node is running the background. +// You can see our `bitcoind` guides to see how to connect +// to a local or remote `bitcoind` node. + +val bitcoindInstance = BitcoindInstanceLocal.fromDatadir() +val rpcCli = BitcoindRpcClient(bitcoindInstance) + +// Next, we need to create a way to monitor the chain: + +val getBestBlockHash = SyncUtil.getBestBlockHashFunc(rpcCli) + +val getBlockHeader = SyncUtil.getBlockHeaderFunc(rpcCli) + +// set a data directory +val datadir = Files.createTempDirectory("bitcoin-s-test") + +// set the current network to regtest +import com.typesafe.config.ConfigFactory +val config = ConfigFactory.parseString { + """ + | bitcoin-s { + | network = regtest + | } + |""".stripMargin +} + +implicit val chainConfig = ChainAppConfig(datadir, config) + +// Initialize the needed database tables if they don't exist: +val chainProjectInitF = chainConfig.start() +val blockHeaderDAO = BlockHeaderDAO() +val compactFilterHeaderDAO = CompactFilterHeaderDAO() +val compactFilterDAO = CompactFilterDAO() + + +//initialize the chain handler from the database +val chainHandler = ChainHandler.fromDatabase(blockHeaderDAO, compactFilterHeaderDAO, compactFilterDAO) + +// Now, do the actual syncing: +val syncedChainApiF = for { + _ <- chainProjectInitF + synced <- ChainSync.sync(chainHandler, getBlockHeader, getBestBlockHash) +} yield synced + +val syncResultF = syncedChainApiF.flatMap { chainApi => + chainApi.getBlockCount().map(count => println(s"chain api blockcount=${count}")) + + rpcCli.getBlockCount.map(count => println(s"bitcoind blockcount=${count}")) +} + +syncResultF.onComplete { case result => + println(s"Sync result=${result}") +} +``` diff --git a/website/versioned_docs/version-1.8.0/node/node-api.md b/website/versioned_docs/version-1.8.0/node/node-api.md new file mode 100644 index 0000000000..1d7a631acd --- /dev/null +++ b/website/versioned_docs/version-1.8.0/node/node-api.md @@ -0,0 +1,83 @@ +--- +id: version-1.8.0-node-api title: Node API +title: node-api title: Node API +original_id: node-api title: Node API +--- + + +### NodeAPI + +The NodeApi is how the wallet project retrieves relevant node data like blocks. This allows the wallet for example to +retrieve blocks for finding its relevant transactions. + +Since this is an API it can be hooked up to the `node` module of bitcoin-s but it can also be linked to any other +implementation of your choosing. This allows you to use the bitcoin-s wallet in any schema that you want. + +The functions that the NodeApi supports are: + +```scala +trait NodeApi { + + /** Request the underlying node to download the given blocks from its peers and feed the blocks to [[org.bitcoins.node.NodeCallbacks]] */ + def downloadBlocks(blockHashes: Vector[DoubleSha256Digest]): Future[Unit] +} +``` + +## Downloading blocks with bitcoind + +As an example, we will show you how to use the `NodeApi` and bitcoind to download blocks for a wallet. + +```scala +implicit val system: ActorSystem = ActorSystem(s"node-api-example") +implicit val ec: ExecutionContextExecutor = system.dispatcher +implicit val walletConf: WalletAppConfig = + BitcoinSTestAppConfig.getSpvTestConfig().walletConf + +// let's use a helper method to get a v19 bitcoind +// and a ChainApi +val instance = BitcoindInstanceLocal.fromConfigFile(BitcoindConfig.DEFAULT_CONF_FILE) +val bitcoind = BitcoindV19RpcClient(instance) +val chainApi = BitcoinSWalletTest.MockChainQueryApi +val aesPasswordOpt = Some(AesPassword.fromString("password")) + +// This function can be used to create a callback for when our node api calls downloadBlocks, +// more specifically it will call the function every time we receive a block, the returned +// NodeCallbacks will contain the necessary items to initialize the callbacks +def createCallback(processBlock: Block => Future[Unit]): NodeCallbacks = { + lazy val onBlock: OnBlockReceived = { block => + processBlock(block) + } + NodeCallbacks(onBlockReceived = Vector(onBlock)) + } + +// Here is a super simple example of a callback, this could be replaced with anything, from +// relaying the block on the network, finding relevant wallet transactions, verifying the block, +// or writing it to disk +val exampleProcessBlock = (block: Block) => + Future.successful(println(s"Received block: ${block.blockHeader.hashBE}")) +val exampleCallback = createCallback(exampleProcessBlock) + +// Here is where we are defining our actual node api, Ideally this could be it's own class +// but for the examples sake we will keep it small. + val nodeApi = new NodeApi { + + override def broadcastTransactions(transactions: Vector[Transaction]): Future[Unit] = { + FutureUtil.sequentially(transactions)(bitcoind.sendRawTransaction(_)).map(_ => ()) + } + + override def downloadBlocks( + blockHashes: Vector[DoubleSha256Digest]): Future[Unit] = { + val blockFs = blockHashes.map(hash => bitcoind.getBlockRaw(hash)) + Future.sequence(blockFs).map(_ => ()) + } + } + +// Finally, we can initialize our wallet with our own node api +val wallet = + Wallet(nodeApi = nodeApi, chainQueryApi = chainApi, feeRateApi = ConstantFeeRateProvider(SatoshisPerVirtualByte.one)) + +// Then to trigger the event we can run +val exampleBlock = DoubleSha256Digest( + "000000000010dc23dc0d5acad64667a7a2b3010b6e02da4868bf392c90b6431d") +wallet.nodeApi.downloadBlocks(Vector(exampleBlock)) +``` diff --git a/website/versioned_docs/version-1.8.0/oracle/oracle-election-example.md b/website/versioned_docs/version-1.8.0/oracle/oracle-election-example.md new file mode 100644 index 0000000000..370652dde5 --- /dev/null +++ b/website/versioned_docs/version-1.8.0/oracle/oracle-election-example.md @@ -0,0 +1,113 @@ +--- +id: version-1.8.0-oracle-election-example +title: Election Example +original_id: oracle-election-example +--- + +## Requirements for example + +You need to have a fully built oracle server. You can follow [this guide](build-oracle-server.md) to do this. + +You will also need a the `bitcoin-s-cli` command line tool to interact with the server. +You can find how to build this [here](../applications/cli.md) + +After building the oracle server, you will need to start it with + +``` +./app/oracle-server/target/universal/stage/bin/bitcoin-s-oracle-server +``` + +## US 2020 Election + +In 2020, the United States held a presidential election. +People want to do a DLC based on the outcome, so you decide to be +their oracle and attest to the winner of the election. + +1. Setting up an oracle that can attest to the outcome of the election +2. Complete the announcement by attesting to the winner of the election + +### Setting up the election bet + +The election bet can be represented by an enumerated announcement. What we mean by this is the outcomes +for this announcement can be simply enumerated in a list. There were three possible outcomes for the election + +1. "Republican_win" +2. "Democrat_win" +3. "other" + +The next step is to create an oracle announcement that can be shared with others. This announcement +contains cryptographic information that is used by people that want to enter into DLCs to setup +their bitcoin transactions. + +To do this, we need to use the `createenumannouncement` rpc. This RPC takes 3 parameters + +1. The label for the announcement + we will use `2020-us-election` +2. the maturation time for the announcement in ISO 8061 format + For our example we will use `"2021-01-20T00:00:00Z"` +3. The outcomes, which we listed above "Republican_win,Democrat_win,other" + +With all of this information, we can create the announcement with `bitcoin-s-cli`! + +``` +./bitcoin-s-cli createenumannouncement 2020-us-election "2021-01-20T00:00:00Z" "Republican_win,Democrat_win,other" +fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e +``` + +Yay! The hex string returned is an oracle announcement. +You can submit this on a tool like the [Suredbits oracle explorer](https://oracle.suredbits.com) +so others can find your oracle. + +If you are building infrastructure to automatically sign announcements, it is important to store two things + +1. The oracle announcement above (`fdd824c...`) +2. The timestamp that the announcement matures at (`"2021-01-20T00:00:00Z"`) + +Now you can schedule jobs to sign the announcement when the maturation time passes. + +### Signing the outcome for the election bet + +In the real world, you would want to wait for the maturation time to pass for your announcement. +For the purposes of the demo, we can skip this wait. The winner of the US election was Joe Biden. + +Let's sign the announcement. + +``` + ./bitcoin-s-cli signenum 2020-us-election Democrat_win +fdd8688010323032302d75732d656c656374696f6ed3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1447a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd75277993590c44656d6f637261745f77696e +``` + +Yay! Now bitcoin-s gives us an attestation that is represented by the hex string `fdd868...` + +If you submitted your announcement to the [suredbits oracle explorer](https://oracle.suredbits.com) above +you will also want to submit the attestation for your announcement so others can find it and settle their DLCs. + +If you use the `getannouncement` rpc along the oracle announcement, you can see the announcement is now completed! + +``` + ./bitcoin-s-cli getannouncement 2020-us-election +{ + "nonces": [ + "ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14" + ], + "eventName": "2020-us-election", + "signingVersion": "DLCOracleV0SigningVersion", + "maturationTime": "2021-01-20T00:00:00Z", + "announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5", + "eventDescriptorTLV": "fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f74686572", + "eventTLV": "fdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e", + "announcementTLV": "fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e", + "attestations": [ + "47a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd7527799359" + ], + "signatures": [ + "ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1447a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd7527799359" + ], + "outcomes": [ + "Republican_win", + "Democrat_win", + "other" + ], + "signedOutcome": "Democrat_win" +} +``` diff --git a/website/versioned_docs/version-1.8.0/oracle/oracle-price-example.md b/website/versioned_docs/version-1.8.0/oracle/oracle-price-example.md new file mode 100644 index 0000000000..2036def41f --- /dev/null +++ b/website/versioned_docs/version-1.8.0/oracle/oracle-price-example.md @@ -0,0 +1,264 @@ +--- +id: version-1.8.0-oracle-price-example +title: Price Example +original_id: oracle-price-example +--- + +## Requirements for example + +You need to have a fully built oracle server. You can follow [this guide](build-oracle-server.md) to do this. + +You will also need a the `bitcoin-s-cli` command line tool to interact with the server. +You can find how to build this [here](../applications/cli.md) + +After building the oracle server, you will need to start it with + +``` +./app/oracle-server/target/universal/stage/bin/bitcoin-s-oracle-server +``` + +## Signing BTC/USD price + +BTC/USD markets trade 24/7/365 around the world. Exchanges publish the market price +for the trading pair everytime a trade is matched in their matching engine. + +In this example, we will + +1. Explain the `createnumericannouncement` and `createdigitdecompannouncement` rpc +2. Set up an oracle that can sign the BTC/USD price at a maturation time +3. Completing the announcement by signing the observed market price + +For this example our maturation time will be + +> 2021-02-04 00:00:00 UTC + +## 2 RPC Options + +When signing numbers, we need to use a [digit decomposition announcement](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Oracle.md#version-0-digit_decomposition_event_descriptor) that can sign +each digit of a number. + +There are 2 different RPC options for making a digit decomposition announcement: `createnumericannouncement` and `createdigitdecompannouncement`. + +`createnumericannouncement` is meant to be user-friendly with an easy to use api, +where `createdigitdecompannouncement` is meant to give to be a more advanced api that gives more expressivity. + +Here we will give examples of each that result in the same announcement. + +### createnumericannouncement rpc + +The `createnumericannouncement` takes 6 arguments + +1. the name for the announcement (`bitcoin-s-price-example`) +2. maturation time in ISO 8601 format (`"2021-02-04T00:00:00Z"`) +3. minimum value (`0`) +4. maximum value (`131071`) +5. units (`BTC/USD`) +6. precision (`base^precision * base^numdigits` to get the actual outcome. This is useful for very small or large values) + +### createdigitdecompannouncement rpc + +It takes 6 arguments + +1. the name for the announcement (`bitcoin-s-price-example`) +2. maturation time in seconds since the epoch (`1612396800`) +3. base (`2`) +4. number of digits (`17`) +5. units (`BTC/USD`) +6. precision (`base^precision * base^numdigits` to get the actual outcome. This is useful for very small or large values) + +### Understanding createdigitdecompannouncement parameters + +Most of these fields are self-explanatory, but one that might confuse new users +is the usage of `base` and `number of digits`. You need to set these two parameters +in such a way that your domain is contained within `base^numdigits`. + +Our domain is BTC/USD price at `2020-02-04 00:00:00 UTC`. That means we need to +pick numDigits such that `2^numDigits` can contain the BTC/USD price at `2020-02-04 00:00:00 UTC` + +For this example, we will pick `numDigits=17`. This means we can sign a BTC/USD price +in between `[0,2^17-1]` or `[$0-$131,071]`. If the BTC/USD price is outside of your +predetermined interval, you need to sign the min (`0`) or the max (`$131,071`). + +## Setting up the BTC/USD oracle + +Given the parameters we specified above, we are ready to create our digit decompisition announcement! + +``` + ./bitcoin-s-cli createdigitdecompannouncement "bitcoin-s-price-example" 1612396800 2 17 "BTC/USD" 0 +fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 +``` + +Yay! The hex string returned is an oracle announcement. +You can submit this on a tool like the [suredbits oracle explorer](https://oracle.suredbits.com) +so others can find your oracle. + +If you are building infrastructure to automatically sign announcements, it is important to store two things + +1. The oracle announcement above (`fdd824fd02b9659...`) +2. The timestamp that the announcement matures at (`1612396800`) + +Now you can schedule jobs to sign the announcement when the maturation time passes. + +## Signing the BTC/USD price for the oracle + +At the maturation time (`2020-02-04 00:00:00 UTC`) you need to check the BTC/USD price. + +For the purposes of this example, we are going to assume the BTC/USD price was `$42,069` BTC/USD. + +Now let's sign the announcement. To do this, we use the `signdigits` rpc. It takes two parameters + +1. The oracle announcement (`fdd824fd02b9659...`) +2. The outcome (`$42,069`) + +``` +./bitcoin-s-cli signdigits "bitcoin-s-price-example" 42069 +fdd868fd049c17626974636f696e2d732d70726963652d6578616d706c650574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a94900114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6c787b447aef7494301823b1570453b6a84bdadb4822cc215b057b3ef4969688f588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274f8ce423054eaccb0e3eadd81395efd9a1fe6c8c70cdb6ce5ade2515593c0306ba7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd2d8d787a6280d88188b85f8c1a8c2b4dc859b408e391037b27c30dd3c2fa1cbf166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5ea403f06f5785e54e43ed84c4ecd73dcda752e0864d61bc406bd4f84495a1ce5988aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e21e1114f3c577d8b7b954505038a9a7372b1546e04ea5c6315d3729c389faa022238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88b3b3e6babdf51b87edab5c22a7a017085488cb3abdabe09e780db34a8860f88ea8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5ddab4419d6859eae05150160029de1065e895e434bddc6a4e0f547572dc661bb719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433a694633a7914f3f155148cceb901ffb81abcb6bc244ce6d28ad6c61c8c9fdd2f7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3bac60fa715ca02a3a801c71afd4d947c7436e05c558194ad7fdd1aeedb3e83eeac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1fb515a7eedb33e4d1ad111c5e2c47b36eae320d5be505293026d4c237e7eac3bf853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533dccce9f582e55e7125bb202820fa4e4ec5ffc2da14c03c3b60d53a0a990d9766b1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd847530ec3fee05a8eeb4919569fa966b7da6960c9f2abf8d884f61c1f5f0895871cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6cc339855ca09a01b9a52ef520f7f328ead330803ab37155d619d8499190ed435c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab666998360d49fdec41fd2165c1c9fa8e880203034fab805b141cf22817d23ace14a0bd22ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f49689493aba5ad6c0cb16c7d862b7cd9747418e0ffec7d3a4ec1ce394d23114bf765aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb828dc8a3114da0cbb7578f57635fcd9daaf1e47cf9214b6605b9a018c1337790ccffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d581ddc2f08d27b7fd895c7fb305dddba5f3bdb923b83c3fdc3560bad5b6044a801300131013001310130013001310130013001300131013001310130013101300131 +``` + +Yay! Now bitcoin-s gives us an attestation that is represented by the hex string `fdd868fd049...` + +If you submitted your announcement to the [suredbits oracle explorer](https://oracle.suredbits.com) above +you will also want to submit the attestation for your announcement so others can find it and settle their DLCs. + +If you use the `getannouncement` rpc along the oracle announcement, you can see the announcement is now completed! + +``` + ./bitcoin-s-cli getannouncement "bitcoin-s-price-example" +{ + "nonces": [ + "4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6", + "588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274", + "a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd", + "166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e", + "88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2", + "238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88", + "a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5", + "719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433", + "7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3", + "ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f", + "853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d", + "1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84", + "cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c", + "104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab6669983", + "2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968", + "aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82", + "ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d" + ], + "eventName": "bitcoin-s-price-example", + "signingVersion": "DLCOracleV0SigningVersion", + "maturationTime": "2021-02-04T00:00:00Z", + "announcementSignature": "659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e5703", + "eventDescriptorTLV": "fdd80a11000200074254432f555344000000000011", + "eventTLV": "fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65", + "announcementTLV": "fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65", + "attestations": [ + "c787b447aef7494301823b1570453b6a84bdadb4822cc215b057b3ef4969688f", + "f8ce423054eaccb0e3eadd81395efd9a1fe6c8c70cdb6ce5ade2515593c0306b", + "2d8d787a6280d88188b85f8c1a8c2b4dc859b408e391037b27c30dd3c2fa1cbf", + "a403f06f5785e54e43ed84c4ecd73dcda752e0864d61bc406bd4f84495a1ce59", + "1e1114f3c577d8b7b954505038a9a7372b1546e04ea5c6315d3729c389faa022", + "b3b3e6babdf51b87edab5c22a7a017085488cb3abdabe09e780db34a8860f88e", + "ddab4419d6859eae05150160029de1065e895e434bddc6a4e0f547572dc661bb", + "a694633a7914f3f155148cceb901ffb81abcb6bc244ce6d28ad6c61c8c9fdd2f", + "bac60fa715ca02a3a801c71afd4d947c7436e05c558194ad7fdd1aeedb3e83ee", + "b515a7eedb33e4d1ad111c5e2c47b36eae320d5be505293026d4c237e7eac3bf", + "ccce9f582e55e7125bb202820fa4e4ec5ffc2da14c03c3b60d53a0a990d9766b", + "7530ec3fee05a8eeb4919569fa966b7da6960c9f2abf8d884f61c1f5f0895871", + "c339855ca09a01b9a52ef520f7f328ead330803ab37155d619d8499190ed435c", + "60d49fdec41fd2165c1c9fa8e880203034fab805b141cf22817d23ace14a0bd2", + "9493aba5ad6c0cb16c7d862b7cd9747418e0ffec7d3a4ec1ce394d23114bf765", + "8dc8a3114da0cbb7578f57635fcd9daaf1e47cf9214b6605b9a018c1337790cc", + "581ddc2f08d27b7fd895c7fb305dddba5f3bdb923b83c3fdc3560bad5b6044a8" + ], + "signatures": [ + "4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6c787b447aef7494301823b1570453b6a84bdadb4822cc215b057b3ef4969688f", + "588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274f8ce423054eaccb0e3eadd81395efd9a1fe6c8c70cdb6ce5ade2515593c0306b", + "a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd2d8d787a6280d88188b85f8c1a8c2b4dc859b408e391037b27c30dd3c2fa1cbf", + "166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5ea403f06f5785e54e43ed84c4ecd73dcda752e0864d61bc406bd4f84495a1ce59", + "88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e21e1114f3c577d8b7b954505038a9a7372b1546e04ea5c6315d3729c389faa022", + "238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88b3b3e6babdf51b87edab5c22a7a017085488cb3abdabe09e780db34a8860f88e", + "a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5ddab4419d6859eae05150160029de1065e895e434bddc6a4e0f547572dc661bb", + "719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433a694633a7914f3f155148cceb901ffb81abcb6bc244ce6d28ad6c61c8c9fdd2f", + "7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3bac60fa715ca02a3a801c71afd4d947c7436e05c558194ad7fdd1aeedb3e83ee", + "ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1fb515a7eedb33e4d1ad111c5e2c47b36eae320d5be505293026d4c237e7eac3bf", + "853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533dccce9f582e55e7125bb202820fa4e4ec5ffc2da14c03c3b60d53a0a990d9766b", + "1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd847530ec3fee05a8eeb4919569fa966b7da6960c9f2abf8d884f61c1f5f0895871", + "cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6cc339855ca09a01b9a52ef520f7f328ead330803ab37155d619d8499190ed435c", + "104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab666998360d49fdec41fd2165c1c9fa8e880203034fab805b141cf22817d23ace14a0bd2", + "2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f49689493aba5ad6c0cb16c7d862b7cd9747418e0ffec7d3a4ec1ce394d23114bf765", + "aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb828dc8a3114da0cbb7578f57635fcd9daaf1e47cf9214b6605b9a018c1337790cc", + "ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d581ddc2f08d27b7fd895c7fb305dddba5f3bdb923b83c3fdc3560bad5b6044a8" + ], + "outcomes": [ + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + [ + "0", + "1" + ], + "signedOutcome": 42069 + ] +} +``` diff --git a/website/versioned_docs/version-1.8.0/oracle/oracle-server.md b/website/versioned_docs/version-1.8.0/oracle/oracle-server.md new file mode 100644 index 0000000000..fbcc392578 --- /dev/null +++ b/website/versioned_docs/version-1.8.0/oracle/oracle-server.md @@ -0,0 +1,195 @@ +--- +id: version-1.8.0-oracle-server +title: Oracle Server +original_id: oracle-server +--- + +The Oracle Server is a DLC Oracle with functionality for creating events and attesting to them. +You can interact with the oracle server with `bitcoin-s-cli` or `curl` + +The following a guide is for interacting with the oracle +If you are looking for the documentation on how to build the oracle server, +checkout [this page](build-oracle-server.md). + +## Server Endpoints + +- `getpublickey` - Get oracle's public key +- `getstakingaddress` - Get oracle's staking address +- `listannouncements` - Lists all event names +- `createenumannouncement` `label` `maturationtime` `outcomes` - Registers an oracle enum event + - `label` - Label for this event + - `maturationtime` - The earliest expected time an outcome will be signed, given in ISO 8601 format + - `outcomes` - Possible outcomes for this event +- `createnumericannouncement` `name` `maturationtime` `minvalue` `maxvalue` `unit` `precision` - Registers an oracle event that uses digit decomposition when signing the number + - `name`- Name for this event + - `maturationtime` - The earliest expected time an outcome will be signed, given in ISO 8601 format + - `minvalue` - Minimum value of this event + - `maxvalue` - Maximum value of this event + - `unit` - The unit denomination of the outcome value + - `precision` - The precision of the outcome representing the base exponent by which to multiply the number represented by the composition of the digits to obtain the actual outcome value. +- `createdigitdecompannouncement` `name` `maturationtime` `base` `numdigits` `unit` `precision` `[signed]` - Registers an oracle event that uses digit decomposition when signing the number + - `name`- Name for this event + - `maturationtime` - The earliest expected time an outcome will be signed, given in epoch second + - `base` - The base in which the outcome value is decomposed + - `numdigits` - The max number of digits the outcome can have + - `unit` - The unit denomination of the outcome value + - `precision` - The precision of the outcome representing the base exponent by which to multiply the number represented by the composition of the digits to obtain the actual outcome value. + - `--signed`- Whether the outcomes can be negative +- `deleteannouncement` `name` - WARNING THIS CAN LEAD TO DLCs NOT SETTLING IF USERS HAVE BUILT DLCS OFF OF THIS ANNOUNCEMENT. USE WITH CARE. + - `name` - Name for this event +- `deleteattestation` `name` - WARNING THIS CAN LEAD TO PRIVATE KEY LEAK IF YOU SIGN ANOTHER ATTESTATION AFTER DELETING A PREVIOUS ONE. USE WITH CARE. + - `name` - Name for this event +- `getannouncement` `event` - Get an event's details + - `eventName` - The event's name +- `signenum` `event` `outcome` - Signs an outcome of an enumerated announcement + - `eventName` - The event's name + - `outcome`- Outcome to sign for this event +- `signdigits` `event` `outcome` - Signs an event + - `eventName` - The event's name + - `outcome` - Number to sign for this event +- `getsignatures` `event` - Get the signatures from a signed event + - `eventName` - The event's name +- `signmessage` `message` - Signs the SHA256 hash of the given string using the oracle's signing key + - `message` - Message to hash and sign +- `backuporacle` `location` - Backs up the oracle database in a safe and consistent manner. + - `location` - The locations of the backup file + +### Create Event Example + +Bitcoin-S CLI: +```bash +$ bitcoin-s-cli createenumannouncement test "2030-01-03T00:30:00.000Z" "outcome1,outcome2,outcome3" +fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374 + +$ bitcoin-s-cli getannouncement test +{ + "nonces": [ + "80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f" + ], + "eventName": "test", + "signingVersion": "DLCOracleV0SigningVersion", + "maturationTime": "2030-01-03T00:30:00.000Z", + "announcementSignature": "ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb90", + "eventDescriptorTLV": "fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d6533", + "eventTLV": "fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374", + "announcementTLV": "fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374", + "attestations": null, + "signatures": null, + "outcomes": [ + "outcome1", + "outcome2", + "outcome3" + ], + "signedOutcome": null +} + + +$ bitcoin-s-cli signenum test "outcome1" +fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531 + +$ bitcoin-s-cli getsignatures test +fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531 +``` + +CURL: +```bash +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "createenumannouncement", "params": ["testEvent", ""2030-01-03T00:30:00.000Z"", ["outcome1", "outcome2", "outcome3"]]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","error":null} + +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getannouncement", "params": ["testEvent"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":{"nonces":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f"],"eventName":"test","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb90","eventDescriptorTLV":"fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d6533","eventTLV":"fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","announcementTLV":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","attestations":["33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"signatures":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"outcomes":["outcome1","outcome2","outcome3",],"signedOutcome": null},"error":null} + +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signenum", "params": ["testEvent", "outcome1"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":"fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531","error":null} + +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getsignatures", "params": ["testEvent"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":["fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531"],"error":null} +``` + +### Numeric Example + +Bitcoin-S CLI: + +```bash +$ bitcoin-s-cli createnumericannouncement exampleNumeric "2030-01-03T00:30:00.000Z" -1000 1000 "units" 0 +fdd824fd010bfc52dab25169eef25815c795128f38ef3b89bc7f53d1d788b4a1c544e5bebfbf6799975b62a1888e2d77445b6d002672f52f8626b1ea6cc6cd974a8039d28a9f5f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822a70004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca5071f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b781492057b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d2949305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd66657131d1fdd80a0f000a0105756e6974730000000000030d6578616d706c654465636f6d70 + +$ bitcoins-cli getannouncement exampleNumeric +{ + "nonces": [ + "012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca5071", + "49305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd66", + "7b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d29", + "f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205" + ], + "eventName": "exampleNumeric", + "signingVersion": "DLCOracleV0SigningVersion", + "maturationTime": "2030-01-03T00:30:00.000Z", + "announcementSignature": "fc52dab25169eef25815c795128f38ef3b89bc7f53d1d788b4a1c544e5bebfbf6799975b62a1888e2d77445b6d002672f52f8626b1ea6cc6cd974a8039d28a9f", + "eventDescriptorTLV": "fdd80a0f000a0105756e697473000000000003", + "eventTLV": "fdd822a70004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca507149305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd667b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d29f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205657131d1fdd80a0f000a0105756e6974730000000000030d6578616d706c654465636f6d70", + "announcementTLV": "fdd824fd010bfc52dab25169eef25815c795128f38ef3b89bc7f53d1d788b4a1c544e5bebfbf6799975b62a1888e2d77445b6d002672f52f8626b1ea6cc6cd974a8039d28a9f5f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822a70004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca507149305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd667b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d29f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205657131d1fdd80a0f000a0105756e6974730000000000030d6578616d706c654465636f6d70", + "attestations": null, + "signatures": null, + "outcomes": [ + [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ], + [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ], + [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9" + ], + [ + "+", + "-" + ] + ], + "signedOutcome": null +} + + +$ bitcoin-s-cli signdigits exampleNumeric 123 +fdd868fd01380d6578616d706c654465636f6d705f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e521150004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca5071a853a189b9acffa2488542c4998261866ce392dbf38031509ceff34077431e65f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205773713008d316640b74d04f180b6c3c09b8de11b29cd7474681a7ad869857cd57b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d294f2222871b23a823acbfa552478ae3d526377a8918b346d6e206156c3e5a2c8549305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd66c03ed28ef6f7b0f48f974b61811a571652ea2eafda5fd5b244674420deb294e8012b013101320133 +``` + +CURL: + +```bash +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "createnumericannouncement", "params": ["numericExample", "2030-01-03T00:30:00.000Z", -1000, 1000, "units", 0]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac0004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf37051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd4756217139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","error":null} + +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getannouncement", "params": ["numericExample"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":{"nonces":["7051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4","7139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2","7446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621","d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3"],"eventName":"numericExample","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b57","eventDescriptorTLV":"fdd80a0f000a0105756e697473000000000003","eventTLV":"fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","announcementTLV":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","attestations":null,"signatures":null,"outcomes":[["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["+","-"]],"signedOutcome": null},"error":null} + +$ curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signdigits", "params": ["numericExample", 123]}' -H "Content-Type: application/json" http://127.0.0.1:9998/ +{"result":"fdd868fd013d126578616d706c6544696769744465636f6d705f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e521150004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3d0646c9efd9523274014841ba24bf63219d5650d1682209d7e48af009d58e6d87051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4c025dfd1e39de77e0418fa7d39abf2e9daf55d7fe34f8e312368cb4d45b4d4b97446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621700347c52af088eda9a0245385094518134e73bb997102e11f6de0aeb36af7237139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2f9e7a9e183b0836ad58dd646d9ab123132397109e4f51c5842958932a81bacd1012b013101320133","error":null} +``` diff --git a/website/versioned_docs/version-1.8.0/rpc/bitcoind.md b/website/versioned_docs/version-1.8.0/rpc/bitcoind.md new file mode 100644 index 0000000000..caf37a842c --- /dev/null +++ b/website/versioned_docs/version-1.8.0/rpc/bitcoind.md @@ -0,0 +1,133 @@ +--- +id: version-1.8.0-rpc-bitcoind +title: bitcoind/Bitcoin Core +original_id: rpc-bitcoind +--- + +## Downloading bitcoind + +The Bitcoin Core RPC client in Bitcoin-S currently supports the Bitcoin Core +- 0.16 +- 0.17 +- 0.18 +- 0.19 +- 0.20 +- 0.21 + +version lines. It can be set up to work with both local and remote Bitcoin Core servers. + +You can fetch them using bitcoin-s by running the following sbt command. If you already have bitcoind installed on your machine, you can skip this step. + + +```bash +sbt downloadBitcoind +``` + +The binaries will be stored in `~/.bitcoin-s/binaries/bitcoind/` + + +## Connecting to a local `bitcoind` instance + +### Getting started quickly, with default options: + +```scala +implicit val ec: ExecutionContext = ExecutionContext.global +implicit val system = ActorSystem("System") +// this reads authentication credentials and +// connection details from the default data +// directory on your platform +val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir")) + +val balance: Future[Bitcoins] = for { + _ <- client.start() + balance <- client.getBalance +} yield balance +``` + +## Multi-wallet `bitcoind` instances + +When using the `bitcoind` with multiple wallets you will need to specify the wallet's name. +To do so the wallet rpc functions have an optional `walletName` parameter. + +```scala +implicit val ec: ExecutionContext = ExecutionContext.global +implicit val system = ActorSystem("System") +val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir")) + +for { + _ <- client.start() + _ <- client.walletPassphrase("mypassword", 10000, Some("walletName")) + balance <- client.getBalance("walletName") +} yield balance +``` + +## Connecting to a remote `bitcoind` + +First, we create a secure connection to our `bitcoind` instance by setting +up a SSH tunnel: + +```bash +ssh -L 8332:localhost:8332 my-cool-user@my-cool-website.com +``` + +> Note: the port number '8332' is the default for mainnet. If you want to +> connect to a testnet `bitcoind`, the default port is '18332' + +Now that we have a secure connection between our remote `bitcoind`, we're +ready to create the connection with our RPC client + +```scala +implicit val ec: ExecutionContext = ExecutionContext.global +implicit val system = ActorSystem("System") +val username = "FILL_ME_IN" //this username comes from 'rpcuser' in your bitcoin.conf file //this username comes from 'rpcuser' in your bitcoin.conf file +val password = "FILL_ME_IN" //this password comes from your 'rpcpassword' in your bitcoin.conf file //this password comes from your 'rpcpassword' in your bitcoin.conf file + +val authCredentials = BitcoindAuthCredentials.PasswordBased( + username = username, + password = password +) + +val bitcoindInstance = { + BitcoindInstanceLocal( + network = MainNet, + uri = new URI(s"http://localhost:${MainNet.port}"), + rpcUri = new URI(s"http://localhost:${MainNet.rpcPort}"), + authCredentials = authCredentials + ) +} + +val rpcCli = BitcoindRpcClient(bitcoindInstance) + +rpcCli.getBalance.onComplete { case balance => + println(s"Wallet balance=${balance}") +} +``` + +## Error handling + +All errors returned by Bitcoin Core are mapped to a corresponding +[`BitcoindException`](https://github.com/bitcoin-s/bitcoin-s/blob/master/bitcoind-rpc/src/main/scala/org/bitcoins/rpc/BitcoindException.scala). +These exceptions contain an error code and a message. `BitcoindException` is a sealed +trait, which means you can easily pattern match exhaustively. Of course, other errors +could also happen: network errors, stack overflows or out-of-memory errors. The provided +class is only intended to cover errors returned by Bitcoin Core. An example of how error +handling could look: + +```scala +implicit val ec = ExecutionContext.global + +// let's assume you have an already running client, +// so there's no need to start this one +val cli = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir")) + +// let's also assume you have a bitcoin address +val address: BitcoinAddress = BitcoinAddress("bc1qm8kec4xvucdgtzppzvvr2n6wp4m4w0k8akhf98") + +val txid: Future[DoubleSha256DigestBE] = + cli.sendToAddress(address, 3.bitcoins).recoverWith { + case BitcoindWalletException.UnlockNeeded(_) => + cli.walletPassphrase("my_passphrase", 60).flatMap { _ => + cli.sendToAddress(address, 3.bitcoins) + } + } +``` diff --git a/website/versioned_docs/version-1.8.0/testkit/testkit.md b/website/versioned_docs/version-1.8.0/testkit/testkit.md new file mode 100644 index 0000000000..a36f443c4b --- /dev/null +++ b/website/versioned_docs/version-1.8.0/testkit/testkit.md @@ -0,0 +1,173 @@ +--- +id: version-1.8.0-testkit +title: Testkit +original_id: testkit +--- + +## Philosophy of Testkit + +The high level of of the bitcoin-s testkit is to mimic and provide functionality to test 3rd party applications. + +There are other examples of these in the Scala ecosystem like the `akka-testkit` and `slick-testkit`. + +We use this testkit to test bitcoin-s it self. + + +### Testkit for bitcoind + +This gives the ability to create and destroy `bitcoind` on the underlying operating system to test against. + +Make sure you have run `sbt downloadBitcoind` before running this example, as you need access to the bitcoind binaries. + +Our [BitcoindRpcClient](/api/org/bitcoins/rpc/client/common/BitcoindRpcClient) is tested with the functionality provided in the testkit. +A quick example of a useful utility method is [BitcoindRpcTestUtil.startedBitcoindRpcClient()](/api/org/bitcoins/testkit/rpc/BitcoindRpcTestUtil). +This spins up a bitcoind regtest instance on machine and generates 101 blocks on that node. + +This gives you the ability to start spending money immediately with that bitcoind node. + +```scala +implicit val system = ActorSystem("bitcoind-testkit-example") +implicit val ec = system.dispatcher + +//pick our bitcoind version we want to spin up +//you can pick older versions if you want +//we support versions 16-19 +val bitcoindV = BitcoindVersion.V19 + +//create an instance +val instance = BitcoindRpcTestUtil.instance(versionOpt = Some(bitcoindV)) + +//now let's create an rpc client off of that instance +val bitcoindRpcClientF = BitcoindRpcTestUtil.startedBitcoindRpcClient(Some(instance), Vector.newBuilder) + +//yay! it's started. Now you can run tests against this. +//let's just grab the block count for an example +val blockCountF = for { + bitcoind <- bitcoindRpcClientF + count <- bitcoind.getBlockCount +} yield { + //run a test against the block count + assert(count > 0, s"Block count was not more than zero!") +} + +//when you are done, don't forget to destroy it! Otherwise it will keep running on the underlying os +val stoppedF = for { + rpc <- bitcoindRpcClientF + _ <- blockCountF + stopped <- BitcoindRpcTestUtil.stopServers(Vector(rpc)) +} yield stopped +``` + +For more information on how the bitcoind rpc client works, see our [bitcoind rpc docs](../rpc/bitcoind.md) + +#### Caching bitcoind in test cases + +When doing integration tests with bitcoind, you likely do not want to spin up a +new bitcoind for _every_ test that is run. + +Not to fear, when using `testkit` you can use our bitcoind fixtures for your unit tests! +These will only spin up on bitcoind per test suite, rather than one bitcoind per test. + +We currently have two types of fixtures available to users of this dependency + +1. [Connected pairs of bitcoind nodes](https://github.com/bitcoin-s/bitcoin-s/blob/eaac9c154c25f3bd76615ea2151092f06df6bdb4/testkit/src/main/scala/org/bitcoins/testkit/rpc/BitcoindFixtures.scala#L282) +2. [Bitcoind nodes with funded wallets](https://github.com/bitcoin-s/bitcoin-s/blob/eaac9c154c25f3bd76615ea2151092f06df6bdb4/testkit/src/main/scala/org/bitcoins/testkit/rpc/BitcoindFixtures.scala#L161) + +If you mixin either of those traits for your test, you will now have access to the corresponding fixture. + +You can find an examples of how to use these two test fixtures + +1. [Example of using a connected pair of nodes in test suite](https://github.com/bitcoin-s/bitcoin-s/blob/32a6db930bdf849a94d92cd1de160b87845ab168/bitcoind-rpc-test/src/test/scala/org/bitcoins/rpc/common/WalletRpcTest.scala#L37) +2. [Example of using a bitcoind with funded wallet in test suite](https://github.com/bitcoin-s/bitcoin-s/blob/eaac9c154c25f3bd76615ea2151092f06df6bdb4/testkit/src/main/scala/org/bitcoins/testkit/rpc/BitcoindFixtures.scala#L161) + + +### Testkit for eclair + +We have similar utility methods for eclair. Eclair's testkit requires a bitcoind running (which we can spin up thanks to our bitcoind testkit). + +Here is an example of spinning up an eclair lightning node, that is connected to a bitcoind and testing your lightning application. + +Make sure to run `sbt downloadBitcoind downloadEclair` before running this so you have access to the underlying eclair binares + +```scala +//Steps: +//1. Open and confirm channel on the underlying blockchain (regtest) +//2. pay an invoice +//3. Await until the payment is processed +//4. assert the node has received the payment +//5. cleanup + +implicit val system = ActorSystem("eclair-testkit-example") +implicit val ec = system.dispatcher + +//we need a bitcoind to connect eclair nodes to +lazy val bitcoindRpcClientF: Future[BitcoindRpcClient] = { + for { + cli <- EclairRpcTestUtil.startedBitcoindRpcClient() + // make sure we have enough money to open channels + address <- cli.getNewAddress + _ <- cli.generateToAddress(200, address) + } yield cli +} + +//let's create two eclair nodes now +val clientF = for { + bitcoind <- bitcoindRpcClientF + e <- EclairRpcTestUtil.randomEclairClient(Some(bitcoind)) +} yield e + +val otherClientF = for { + bitcoind <- bitcoindRpcClientF + e <- EclairRpcTestUtil.randomEclairClient(Some(bitcoind)) +} yield e + +//great, setup done! Let's run the test +//to verify we can send a payment over the channel +for { + client <- clientF + otherClient <- otherClientF + _ <- EclairRpcTestUtil.openAndConfirmChannel(clientF, otherClientF) + invoice <- otherClient.createInvoice("abc", 50.msats) + info <- otherClient.getInfo + _ = assert(info.nodeId == invoice.nodeId) + infos <- client.getSentInfo(invoice.lnTags.paymentHash.hash) + _ = assert(infos.isEmpty) + paymentId <- client.payInvoice(invoice) + _ <- EclairRpcTestUtil.awaitUntilPaymentSucceeded(client, paymentId) + sentInfo <- client.getSentInfo(invoice.lnTags.paymentHash.hash) +} yield { + assert(sentInfo.head.amount == 50.msats) +} + +//don't forget to shutdown everything! +val stop1F = clientF.map(c => EclairRpcTestUtil.shutdown(c)) + +val stop2F = otherClientF.map(o => EclairRpcTestUtil.shutdown(o)) + +val stoppedBitcoindF = for { + bitcoind <- bitcoindRpcClientF + _ <- BitcoindRpcTestUtil.stopServers(Vector(bitcoind)) +} yield () + + +val resultF = for { + _ <- stop1F + _ <- stop2F + _ <- stoppedBitcoindF + _ <- system.terminate() +} yield () + +Await.result(resultF, 180.seconds) +``` + +### Other modules + +You may find useful testkit functionality for other modules here + +1. [Chain](/api/org/bitcoins/testkit/chain/ChainUnitTest) +2. [Key Manager](/api/org/bitcoins/testkit/keymanager/KeyManagerApiUnitTest) +3. [Wallet](/api/org/bitcoins/testkit/wallet/BitcoinSWalletTest) +4. [Node](/api/org/bitcoins/testkit/node/NodeUnitTest) + +In general, you will find constructors and destructors of fixtures that can be useful when testing your applications +if you are using any of those modules. diff --git a/website/versioned_docs/version-1.8.0/wallet/dlc.md b/website/versioned_docs/version-1.8.0/wallet/dlc.md new file mode 100644 index 0000000000..00e0c9973c --- /dev/null +++ b/website/versioned_docs/version-1.8.0/wallet/dlc.md @@ -0,0 +1,322 @@ +--- +id: version-1.8.0-dlc +title: Executing A DLC with Bitcoin-S +original_id: dlc +--- + +## Executing A Discreet Log Contract (DLC) + +## Step 1: Get Bitcoin-S Setup + +See the [setup document](../getting-setup.md). + +### Using the GUI + +To first start up the GUI you first need to start your bitcoin-s server and gui with + +```bashrc +sbt bundle/run +``` + +or if your bitcoin-s server is already running, you can run the standalone gui with + +```bashrc +sbt gui/run +``` + +or by following the instructions for building and running the GUI [here](../getting-setup.md#step-5-setting-up-a-bitcoin-s-server) + +## Step 2: Agree On Contract Terms + +Both parties must agree on all fields from the table below: + +| Field Name | Description | +| :------------: | :------------------------------------------------------: | +| contractInfo | Information about payouts and which oracles to use | +| collateral | Number of sats the initiator is putting up | +| locktime | Locktime of the CETs | +| refundlocktime | Locktime of the Refund Transaction | +| feerate | Fee rate in sats/vbyte | + +> Note: if you wish to set up your own oracle for testing, you can do so by checking out our [oracle rpc server](../oracle/oracle-server.md) or [Krystal Bull](https://github.com/bitcoin-s/krystal-bull) + +### Decoding DLC Messages + +With the cli tool you can decode dlc offers, contract infos, oracle announcements, and oracle attestations. +This can be helpful for when developing on top of bitcoin-s and not having the proper DLC tooling to understand the messages. + +Examples: + +Decoding Offer: +```bash +bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82ee40000000000010f2cfda7101802035965730000000000010f2c024e6f0000000000000000fda712bcfdd824b8d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68fdd822540001ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f60dfa880fdd80609000203596573024e6f20446f657320746865206d656d706f6f6c20636c656172206f6e20372f322f323102279cf17c387d7101b08d90b2aeef46231957d9d3558f5871e62781a68e7d75c9001600148dc81a3097bf28c6020eaf89cefae69c5f31aceb5d655d867008d23e00000000000090880001fda714fd01b3627231e09b7948c3019d02000000000102368af13baeef5a313d3ef12e895b232f1e76212cb76957d7e4b8a664915d15960100000000fdfffffffaec4ef43ae2365d0abc53336188053da4078a5b7489928602bcc8c9a4b75f0d0000000000fdffffff030f0b000000000000160014107eb2463ad25843ed01fd33656c83bdd11db3554a8701000000000022002002265c41f299b3c7f0dda5b9d7bc4135d25c2d8aed286837aa9e0954d70894d606961c000000000016001482a7ecd4624e6856d1b09c27e9f3a82323f49c2d0247304402200911162e99e23e4a26e0219a4bdaaf7a5f790be63a8376516640dcc0860ca4d602203a078371904842e2e6adfbebebcac138db23514b3396851569f5f2bf82c3197a012103cd2d0a4eace5993ebb0a75da85d9070627e64f1a5783cf5217e9bd82d20d1c470247304402200fa8515323410ca2b14b08bf22c618b6ced77b9289cb1dfa7ac10548e2e1b2e002206a407bcafdfb64009182fb5838db9671968abdd902e1194f6883cd0e5413ad36012103d3864eb755690e2b4ff139047419373e36a05630429da76fef5de25eeffb4ffc0000000000000002fffffffd006b000000160014d13be5f330b1ea9bbf61f68002b4465e02c341d9df27e1460161e002825311ec94d1e91b000000000000000a0000000061316580 +{ + "contractFlags": "0", + "chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + "contractInfo": { + "totalCollateral": 69420, + "contractDescriptor": { + "outcomes": [ + { + "outcome": "Yes", + "localPayout": 69420 + }, + { + "outcome": "No", + "localPayout": 0 + } + ] + }, + "oracleInfo": { + "announcement": { + "announcementSignature": "d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2", + "publicKey": "b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68", + "event": { + "nonces": [ + "ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f" + ], + "maturity": "2021-07-03T00:00:00Z", + "descriptor": { + "outcomes": [ + "Yes", + "No" + ] + }, + "eventId": "Does the mempool clear on 7/2/21" + } + } + } + }, + "fundingPubKey": "02279cf17c387d7101b08d90b2aeef46231957d9d3558f5871e62781a68e7d75c9", + "payoutSPK": "1600148dc81a3097bf28c6020eaf89cefae69c5f31aceb", + "payoutSerialId": 6729888050161701888, + "offerCollateralSatoshis": 37000, + "fundingInputs": [ + { + "inputSerialId": 7093787203812804608, + "prevTx": "02000000000102368af13baeef5a313d3ef12e895b232f1e76212cb76957d7e4b8a664915d15960100000000fdfffffffaec4ef43ae2365d0abc53336188053da4078a5b7489928602bcc8c9a4b75f0d0000000000fdffffff030f0b000000000000160014107eb2463ad25843ed01fd33656c83bdd11db3554a8701000000000022002002265c41f299b3c7f0dda5b9d7bc4135d25c2d8aed286837aa9e0954d70894d606961c000000000016001482a7ecd4624e6856d1b09c27e9f3a82323f49c2d0247304402200911162e99e23e4a26e0219a4bdaaf7a5f790be63a8376516640dcc0860ca4d602203a078371904842e2e6adfbebebcac138db23514b3396851569f5f2bf82c3197a012103cd2d0a4eace5993ebb0a75da85d9070627e64f1a5783cf5217e9bd82d20d1c470247304402200fa8515323410ca2b14b08bf22c618b6ced77b9289cb1dfa7ac10548e2e1b2e002206a407bcafdfb64009182fb5838db9671968abdd902e1194f6883cd0e5413ad36012103d3864eb755690e2b4ff139047419373e36a05630429da76fef5de25eeffb4ffc00000000", + "prevTxVout": 2, + "sequence": 4294967293, + "maxWitnessLen": 107, + "redeemScript": null + } + ], + "changeSPK": "160014d13be5f330b1ea9bbf61f68002b4465e02c341d9", + "changeSerialId": 1.6080068685336797E19, + "fundOutputSerialId": 9.390869355804355E18, + "feeRatePerVb": 10, + "cetLocktime": 0, + "refundLocktime": 1630627200 +} +``` + +Decoding Contract Info: +```bash +bitcoin-s-cli decodecontractinfo fdd82ee40000000000010f2cfda7101802035965730000000000010f2c024e6f0000000000000000fda712bcfdd824b8d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68fdd822540001ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f60dfa880fdd80609000203596573024e6f20446f657320746865206d656d706f6f6c20636c656172206f6e20372f322f3231 +{ + "totalCollateral": 69420, + "contractDescriptor": { + "outcomes": [ + { + "outcome": "Yes", + "localPayout": 69420 + }, + { + "outcome": "No", + "localPayout": 0 + } + ] + }, + "oracleInfo": { + "announcement": { + "announcementSignature": "d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2", + "publicKey": "b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68", + "event": { + "nonces": [ + "ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f" + ], + "maturity": "2021-07-03T00:00:00Z", + "descriptor": { + "outcomes": [ + "Yes", + "No" + ] + }, + "eventId": "Does the mempool clear on 7/2/21" + } + } + } +``` + +Decoding Oracle Announcement: +```bash +bitcoin-s-cli decodeannouncement fdd824b1585e18c3bc1d922854329fdb5a402713b161b7baebb6b6f3249936ef79c0a6671027afd7a1126d79e589811042eb4885c0cb7c150b4c4863a1e35a2ac432f7c81d5dcdba2e64cb116cc0c375a0856298f0058b778f46bfe625ac6576204889e4fdd8224d0001424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474603c2e80fdd80609000203594553024e4f194254432d5553442d4f5645522d35304b2d434f494e42415345 +{ + "announcementSignature": "585e18c3bc1d922854329fdb5a402713b161b7baebb6b6f3249936ef79c0a6671027afd7a1126d79e589811042eb4885c0cb7c150b4c4863a1e35a2ac432f7c8", + "publicKey": "1d5dcdba2e64cb116cc0c375a0856298f0058b778f46bfe625ac6576204889e4", + "event": { + "nonces": [ + "424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474" + ], + "maturity": "2021-03-01T00:00:00Z", + "descriptor": { + "outcomes": [ + "YES", + "NO" + ] + }, + "eventId": "BTC-USD-OVER-50K-COINBASE" + } +} +``` + +Decoding Oracle Attestations +```bash +bitcoin-s-cli decodeattestments fdd8687f194254432d5553442d4f5645522d35304b2d434f494e424153451d5dcdba2e64cb116cc0c375a0856298f0058b778f46bfe625ac6576204889e40001424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474de6b75f1da183a2a4f9ad144b48bf1026cee9687221df58f04128db79ca17e2a024e4f +{ + "eventId": "BTC-USD-OVER-50K-COINBASE", + "signatures": [ + "424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474de6b75f1da183a2a4f9ad144b48bf1026cee9687221df58f04128db79ca17e2a" + ], + "values": [ + "NO" + ] +} +``` + +## Step 3: Set up The DLC + +### Using the GUI + +If you're a visual learner there is a [video demo](https://www.youtube.com/watch?v=zy1sL2ndcDg) that explains this process in detail. +But do note that this demonstrates the old non-adaptor version of DLCs so that the Offer, Accept, Sign protocol is the same, but the contents will be different. + +If using a numeric contract and/or multiple oracles, messages can get very large and sometimes even too large to for the application. +To solve this there is an `Export to file` button located under the text box for the messages your wallet will construct. +This can be used to export a DLC message to a file and then the file can be sent to your counterparty. +If you receive a file from a counter-party, there is an `Import file` button on every dialog you input a DLC message. +This can be used to import the file of the DLC message from your counter-party. + +#### Creating The Offer + +Once the terms are agreed to, either party can use the `Offer` button and enter each of the fields from the table above. + +#### Accepting The Offer + +Upon receiving a DLC Offer from your counter-party, you can use the `Accept` button and paste in the DLC Offer. + +#### Signing The DLC + +Upon receiving a DLC Accept message from your counter-party, you can use the `Sign` button and paste in the DLC Accept. + +#### Adding DLC Signatures To Your Database + +Upon receiving a DLC Sign message from your counter-party, add their signatures to your database using the `Add Sigs` button and paste in the message. +After doing so you can get the fully signed funding transaction using the `Get Funding Tx` button. This will return the fully signed serialized transaction. + +### Using the CLI + +If using a numeric contract and/or multiple oracles, messages can get very large and sometimes even too large to for the application. +To solve this there are RPC calls where you can give a file instead of the entire DLC message. +To output a file you simply just need to pipe the output of a command into a file. + +For example: +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli acceptdlcoffer [offer] > myDLCAccept.txt +``` + +#### Creating The Offer + +Once these terms are agreed to, either party can call on `createdlcoffer` with flags for each of the fields in the table above. For example: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli createdlcoffer [contractInfo] [collateral] [feerate] [locktime] [refundlocktime] +``` + +#### Accepting The Offer + +Upon receiving a DLC Offer from your counter-party, the following command will create the serialized accept message: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli acceptdlcoffer [offer] +``` + +or from file: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli acceptdlcofferfromfile [filepath] +``` + +#### Signing The DLC + +Upon receiving a DLC Accept message from your counter-party, the following command will generate all of your signatures for this DLC: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli signdlc [accept] +``` + +or from file: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli signdlcfromfile [filepath] +``` + + +#### Adding DLC Signatures To Your Database + +Upon receiving a DLC Sign message from your counter-party, add their signatures to your database by: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli adddlcsigs [sign] +``` + +or from file: + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli adddlcsigsfromfile [filepath] +``` + +#### Getting Funding Transaction + +You are now fully setup and can generate the fully signed funding transaction for broadcast using + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli getdlcfundingtx [contractId] +``` + +where the `contractId` is in all but the messages other than the DLC Offer message, and is also returned by the `adddlcsigs` command. + +Alternatively, you can use the `getdlcs` command to list all of your current DLCs saved in your wallet. + +## Step 4: Executing the DLC + +### Using the GUI + +#### Execute + +You can execute the DLC unilaterally with the `Execute` button which will require the oracle signature. +This will return a fully signed Contract Execution Transaction for the event signed by the oracle. + +#### Refund + +If the `refundlocktime` for the DLC has been reached, you can get the fully-signed refund transaction with the `Refund` button and entering the `contractId`. + +### Using the CLI + +#### Execute + +Upon receiving an oracle signature, you can execute the DLC unilaterally with + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli executedlc [contractId] [signatureTLVs] +``` + +which will return fully signed Contract Execution Transaction for the event signed by the oracle. + +#### Refund + +If the `refundlocktime` for the DLC has been reached, you can get the fully-signed refund transaction with + +```bashrc +./app/cli/target/universal/stage/bitcoin-s-cli executedlcrefund [contractId] +``` diff --git a/website/versioned_docs/version-1.8.0/wallet/wallet-election-example.md b/website/versioned_docs/version-1.8.0/wallet/wallet-election-example.md new file mode 100644 index 0000000000..18446e8f06 --- /dev/null +++ b/website/versioned_docs/version-1.8.0/wallet/wallet-election-example.md @@ -0,0 +1,319 @@ +--- +id: version-1.8.0-wallet-election-example +title: Wallet Election Example +original_id: wallet-election-example +--- + +This is a developer example to show to how build a +DLC with `bitcoin-s-cli` utility using the oracle +we built in our [oracle election example](../oracle/oracle-election-example.md) + +This example will show you to collaborate with your peer +to create the funding transaction for your DLC. + +The last thing we will do is close the DLC by broadcasting +the contract execution transaction (CET) that is valid after +the oracle broadcasts its attestations. + +## Requirements for example + +You need to have a fully built DLC wallet. +You can follow [this guide](../applications/server.md#building-the-server) to do this. + +You will also need a the `bitcoin-s-cli` command line tool to interact with the server. +You can find how to build this [here](../applications/cli.md) + +Since bitcoin-s is a self custodial wallet, you will need to either + +1. [Connect your server to bitcoind](../getting-setup.md#bitcoind-backend) +2. [Do intial block download (IBD) with blockfilters](../getting-setup.md#neutrino-node). This can take a few hours. + +``` +./app/server/target/universal/stage/bin/bitcoin-s-server +``` + +## US 2020 election + +In 2020, the United States held a presidential election. +People want to do a DLC based on the outcome. + +### Setting up the election bet + +#### Oracle +The first thing you need to create a DLC is an oracle that +is attesting to the real world event that you are interested in. + +In this case, we will be using the oracle we setup in our +[oracle election example](../oracle/oracle-election-example.md). + +The announcement that this oracle produced is + +``` +fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e +``` + +This announcement contains all the cryptographic information +necessary for you and your counterparty to build a DLC. + +#### Contract + +The next step for building a DLC is agreeing to a [contract info](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-contract_info-type). +A contract info contains information about + +1. The oracles that will be used by the DLC +2. The contract payout conditions based on the oracle. + +Up until this point all information in this example does +NOT contain any information specific to the bitcoin network. + +If the oracle has published their announcement to the +Suredbits oracle explorer, you can build this +[via the contract explorer](https://test.oracle.suredbits.com/event/8863cd80e1d37f668e27b84cbfed48541d671b4fed1462b86d547e7f13b5a9e4/contracts/new). + +[Here](https://test.oracle.suredbits.com/contract/enum/f3650e03487941be8d3285f3eecd3689cbb9c4b49d1c6d467f92399647c45703) +is a completed example of what we are going to build via the `bitcoin-s-cli` + +Alice has decided that she wants to do a 100,000 sats bet. +The amount of collateral Alice is going to contribute to the bet +is `60,000` sats. + +Bob, Alice's counterparty, has agreed to contribute +`40,000` sats in collateral to the bet. + +The next step is to create a `contractinfo` locally that represents +this bet. We can do this with the `createcontractinfo` rpc + +``` +./bitcoin-s-cli createcontractinfo fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e \ +100000 \ +"{\"outcomes\" : { \"Republican_win\" : 0, \"Democrat_win\" : 100000, \"other\" : 60000 }}" + +fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e +``` + +We can decode the encoded contract info (`fdd82efd011...`) with the `decodecontractinfo` to see what this represents + +``` +/bitcoin-s-cli decodecontractinfo fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e + +{ + "totalCollateral": 100000, + "contractDescriptor": { + "outcomes": { + "Republican_win": 0, + "Democrat_win": 100000, + "other": 60000 + } + }, + "oracleInfo": { + "announcement": { + "announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5", + "publicKey": "d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a", + "event": { + "nonces": [ + "ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14" + ], + "maturity": "2021-02-02T00:00:00Z", + "descriptor": { + "outcomes": [ + "Republican_win", + "Democrat_win", + "other" + ] + }, + "eventId": "2020-us-election" + } + } + } +} + +``` + +### Building funding tx/dlcs with your counterparty + +Now that the contract terms are agreed upon, the next thing you need to do is +begin the [negotiation protocol](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#contract-negotiation) with your counterparty. + +#### Offer +The first thing you need to send your counterparty is an [`offer`](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#the-offer_dlc-message). +This message contains information about the utxos you will use to fund your side of the funding transaction. + +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 + +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` + +Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral. + +``` +./bitcoin-s-cli createdlcoffer fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e \ +60000 \ +1 \ +0 \ +705417 +a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389 +``` + +Yay! We have now created an offer (`a71a006fe...`) that we can send to our counterparty, Bob. If you would like to review +the offer before sending it to him you can use `decodeoffer` + +``` +./bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389 +{ + "contractFlags": "0", + "chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + "contractInfo": { + "totalCollateral": 100000, + "contractDescriptor": { + "outcomes": { + "Republican_win": 0, + "Democrat_win": 100000, + "other": 60000 + } + }, + "oracleInfo": { + "announcement": { + "announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5", + "publicKey": "d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a", + "event": { + "nonces": [ + "ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14" + ], + "maturity": "2021-02-02T00:00:00Z", + "descriptor": { + "outcomes": [ + "Republican_win", + "Democrat_win", + "other" + ] + }, + "eventId": "2020-us-election" + } + } + } + }, + "fundingPubKey": "02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0", + "payoutSPK": "1600141df0a84b2d2e611dd595101bfed6320143c47ebb", + "payoutSerialId": 1.2572776984081695E19, + "offerCollateralSatoshis": 60000, + "fundingInputs": [ + { + "inputSerialId": 9.751703500876681E18, + "prevTx": "02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a000000000", + "prevTxVout": 1, + "sequence": 4294967293, + "maxWitnessLen": 107, + "redeemScript": null + } + ], + "changeSPK": "160014eff30273b9aa3feb39fee0916a09bf2c2477df0a", + "changeSerialId": 2059450458141810176, + "fundOutputSerialId": 1.1508893674044221E19, + "feeRatePerVb": 1, + "cetLocktime": 0, + "refundLocktime": 705417 +} +``` + +The final thing Alice needs to give bob is here wallet's tor address. This is used to interactively +build and verify contract execution transactions (CET). This can be done in a manual fashion, but I'm skipping +this for the sake of brevity and better UX. Please contact me if you would like manual steps with no built in networking. + +Alice can retrieve her dlc host address with +``` +./bitcoin-s-cli getdlchostaddress +v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 +``` + +She always needs to send this Bob. + +#### Accept + +Once Bob has received Alice's dlc host address and the offer, and reviews the terms of the offer with `decodeoffer`, he +can accept the offer. + +``` +./bitcoin-s-cli acceptdlc a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389 v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 + +``` + +Currently this RPC doesn't return anything, but if you look at logs you should see your funding tx broadcast. +You can find logs at `~/.bitcoin-s/{mainnet,testnet3,regtest}/bitcoin-s.log` + +``` +[info] 2021-10-03T21:02:52UTC INFO [DLCClient] connecting to SOCKS5 proxy localhost/127.0.0.1:49196 +[info] 2021-10-03T21:02:52UTC INFO [DLCClient] connected to SOCKS5 proxy localhost/127.0.0.1:49196 +[info] 2021-10-03T21:02:52UTC INFO [DLCClient] connecting to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion/:2862 via SOCKS5 localhost/127.0.0.1:49196 +[info] 2021-10-03T21:03:02UTC INFO [DLCClient] connected to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion/:2862 via SOCKS5 proxy localhost/127.0.0.1:49196 +[info] 2021-10-03T21:03:02UTC INFO [DLCDataHandler] Received LnMessage DLCOfferTLV +[info] 2021-10-03T21:03:02UTC INFO [DLCWallet$DLCWalletImpl] Creating DLC Accept for tempContractId a4e127a34eb1fc998018bfc4a7e1a6943f6588d765b1e36ca6b9c7cc67b7eaa8 +[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] Spending UTXOs: 3ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b766:0 +[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] UTXO 0 details: TransactionOutput(4466999 sats,wpkh(dca26092b7540ba1c7bea286f73955a7cb247dd9)) +[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] Creating CET Sigs for a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] Created DLCAccept for tempContractId a4e127a34eb1fc998018bfc4a7e1a6943f6588d765b1e36ca6b9c7cc67b7eaa8 with contract Id a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:04UTC INFO [DLCDataHandler] Received LnMessage DLCSignTLV +[info] 2021-10-03T21:03:04UTC INFO [DLCWallet$DLCWalletImpl] Verifying CET Signatures for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:04UTC INFO [DLCWallet$DLCWalletImpl] CET Signatures are valid for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:04UTC INFO [DLCWallet$DLCWalletImpl] Verifying 1 funding sigs for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] DLC a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 sigs are verified and stored, ready to broadcast +[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Created funding transaction 0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91 for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Broadcasting funding transaction 0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91 for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 +[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Adding UTXO to wallet: 91de6518fbf9eb656d9690224655049f5f21ac1c2189a142b1e0ce586989740d:2 amt=4426788 sats +[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Successfully inserted UTXO 91de6518fbf9eb656d9690224655049f5f21ac1c2189a142b1e0ce586989740d:2 into DB +[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Processing tx 0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91 for 1 DLC(s) +``` + +You can check the state of the DLC with `getdlcs` + +``` +./bitcoin-s-cli getdlcs +[ + { + "state": "Broadcasted", + "dlcId": "2f1224d3ab1f2456d020e7777009153e2ee5db2d127b94774580e428f5a899b9", + "isInitiator": false, + "lastUpdated": "2021-10-03T21:03:05.539Z", + "tempContractId": "a4e127a34eb1fc998018bfc4a7e1a6943f6588d765b1e36ca6b9c7cc67b7eaa8", + "contractId": "a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439", + "contractInfo": "fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e", + "contractMaturity": 704409, + "contractTimeout": 705417, + "feeRate": 1, + "totalCollateral": 100000, + "localCollateral": 40000, + "remoteCollateral": 60000, + "fundingTxId": "0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91" + } +] +``` + +You can find things like the `fundingTxId`, `state`, `dlcId`, and `contractId` from this RPC call. Since we just +broadcast the funding transaction, the state of the DLC is `Broadcast`. + +### Settling the DLC + +Once the oracle has broadcast their attestations, a user can close out the DLC. +In this case of this example, you can find the oracle +attestations [on the oracle explorer](https://test.oracle.suredbits.com/announcement/8863cd80e1d37f668e27b84cbfed48541d671b4fed1462b86d547e7f13b5a9e4) + +``` +fdd8688010323032302d75732d656c656374696f6ed3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1447a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd75277993590c44656d6f637261745f77696e +``` + +We will need the contract id to close the DLC. This can be found using the `getdlcs` RPC. +Our contract id is `a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439` + +``` +./bitcoin-s-cli executedlc a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 fdd8688010323032302d75732d656c656374696f6ed3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1447a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd75277993590c44656d6f637261745f77696e +3cad29be34216e279d13f19153f296c4e3f8240d4a1aa04eb96a3c275478c4d1 +``` + +The thing returned is the CET's txid. + +You've now settled your DLC :tada: :tada: \ No newline at end of file diff --git a/website/versioned_docs/version-1.8.0/wallet/wallet-price-example.md b/website/versioned_docs/version-1.8.0/wallet/wallet-price-example.md new file mode 100644 index 0000000000..5bdb4f3146 --- /dev/null +++ b/website/versioned_docs/version-1.8.0/wallet/wallet-price-example.md @@ -0,0 +1,406 @@ +--- +id: version-1.8.0-wallet-price-example +title: Wallet Price Example +original_id: wallet-price-example +--- + +This is a developer example to show to how build a +DLC with `bitcoin-s-cli` utility using the oracle +we built in our [oracle price example](../oracle/oracle-price-example.md) + +This example will show you to collaborate with your peer +to create the funding transaction for your DLC. + +The last thing we will do is close the DLC by broadcasting +the contract execution transaction (CET) that is valid after +the oracle broadcasts its attestations. + +## Requirements for example + +You need to have a fully built DLC wallet. +You can follow [this guide](../applications/server.md#building-the-server) to do this. + +You will also need a the `bitcoin-s-cli` command line tool to interact with the server. +You can find how to build this [here](../applications/cli.md) + +Since bitcoin-s is a self custodial wallet, you will need to either + +1. [Connect your server to bitcoind](../getting-setup.md#bitcoind-backend) +2. [Do intial block download (IBD) with blockfilters](../getting-setup.md#neutrino-node). This can take a few hours. + +``` +./app/server/target/universal/stage/bin/bitcoin-s-server +``` + +## Betting on bitcoin + +New financial markets are being built for bitcoin. Users are interested in financial +products designed to speculate on the price of bitcoin. + +#### Oracle + +The first thing you need to create a DLC is an oracle that +is attesting to the real world event that you are interested in. + +In this case, we will be using the oracle we setup in our +[oracle election example](../oracle/oracle-price-example.md#setting-up-the-btcusd-oracle). + +The announcement that this oracle produced is + +``` +fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 +``` + +This announcement contains all the cryptographic information +necessary for you and your counterparty to build a DLC. + +#### Contract + +The next step for building a DLC is agreeing to a [contract info](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-contract_info-type). +A contract info contains information about + +1. The oracles that will be used by the DLC +2. The contract payout conditions based on the oracle. + +Up until this point all information in this example does +NOT contain any information specific to the bitcoin network. + +If the oracle has published their announcement to the +Suredbits oracle explorer, you can build this +[via the contract explorer](https://test.oracle.suredbits.com/event/362ae482860fc93bac5cbcca3f1f0e49b3c94eac92224a008bd81ef81292f43a/contracts/new). + +[Here](https://test.oracle.suredbits.com/contract/numeric/d4d4df2892fb2cfd2e8f030f0e69a568e19668b5d355e7713f69853db09a4c33) +is a completed example of what we are going to build via the `bitcoin-s-cli` + +Alice has decided that she wants to do a 1 bitcoin bet. +The amount of collateral Alice is going to contribute to the bet +is `50,000` sats. + +Bob, Alice's counterparty, has agreed to contribute +`50,000` sats in collateral to the bet. + +The next step is to create a `contractinfo` [via the contract explorer hosted by Suredbits](https://test.oracle.suredbits.com/contract/numeric/d4d4df2892fb2cfd2e8f030f0e69a568e19668b5d355e7713f69853db09a4c33) +or locally that represents this bet. + +These next instructions are for if you decide to build it locally. + +We can do this with the `createcontractinfo` rpc + +``` +./bitcoin-s-cli createcontractinfo fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \ +100000 \ +"[{\"outcome\":0,\"payout\":0,\"extraPrecision\":0,\"isEndpoint\":true}, \ + {\"outcome\":40000,\"payout\":0,\"extraPrecision\":0,\"isEndpoint\":true}, \ + {\"outcome\":42500,\"payout\":50000,\"extraPrecision\":0,\"isEndpoint\":true}, \ + {\"outcome\":45000,\"payout\":100000,\"extraPrecision\":0,\"isEndpoint\":true}, \ + {\"outcome\":131071,\"payout\":100000,\"extraPrecision\":0,\"isEndpoint\":true}]" + +fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 +``` + +The `fdd824fd02b96...` is the oracle announcement, the `100000` is the total collateral in the DLC +and the final json datstructure is the points on the payout curve. The x-axis is `outcome` +and the y axis is `payout`. + +You can decode this contract info with `decodecontractinfo` + +``` + ./bitcoin-s-cli decodecontractinfo fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77cbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 + +{ + "totalCollateral": 100000, + "contractDescriptor": { + "numDigits": 17, + "payoutFunction": { + "points": [ + { + "outcome": 0, + "payout": 0, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 40000, + "payout": 0, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 42500, + "payout": 50000, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 45000, + "payout": 100000, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 131071, + "payout": 100000, + "extraPrecision": 0, + "isEndpoint": true + } + ] + }, + "roundingIntervals": { + "intervals": [] + } + }, + "oracleInfo": { + "announcement": { + "announcementSignature": "659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e5703", + "publicKey": "0574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949", + "event": { + "nonces": [ + "4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6", + "588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274", + "a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd", + "166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e", + "88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2", + "238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88", + "a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5", + "719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433", + "7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3", + "ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f", + "853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d", + "1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84", + "cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c", + "104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab6669983", + "2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968", + "aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82", + "ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d" + ], + "maturity": "2021-02-04T00:00:00Z", + "descriptor": { + "base": 2, + "isSigned": false, + "unit": "BTC/USD", + "precision": 0 + }, + "eventId": "bitcoin-s-price-example" + } + } + } +} +``` + +### Building funding tx/dlcs with your counterparty + +Now that the contract terms are agreed upon, the next thing you need to do is +begin the [negotiation protocol](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#contract-negotiation) with your counterparty. + +#### Offer + +The first thing you need to send your counterparty is an [`offer`](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#the-offer_dlc-message). +This message contains information about the utxos you will use to fund your side of the funding transaction. + +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 + +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` + +Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral. + +``` +./bitcoin-s-cli createdlcoffer fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \ +50000 \ +1 \ +0 \ +> 707177 \ +a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69 +``` + +You can decode the offer above with `decodeoffer` + +``` +./bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69 +{ + "contractFlags": "0", + "chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000", + "contractInfo": { + "totalCollateral": 100000, + "contractDescriptor": { + "numDigits": 17, + "payoutFunction": { + "points": [ + { + "outcome": 0, + "payout": 0, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 40000, + "payout": 0, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 42500, + "payout": 50000, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 45000, + "payout": 100000, + "extraPrecision": 0, + "isEndpoint": true + }, + { + "outcome": 131071, + "payout": 100000, + "extraPrecision": 0, + "isEndpoint": true + } + ] + }, + "roundingIntervals": { + "intervals": [] + } + }, + "oracleInfo": { + "announcement": { + "announcementSignature": "659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e5703", + "publicKey": "0574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949", + "event": { + "nonces": [ + "4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6", + "588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274", + "a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd", + "166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e", + "88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2", + "238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88", + "a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5", + "719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433", + "7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3", + "ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f", + "853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d", + "1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84", + "cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c", + "104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab6669983", + "2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968", + "aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82", + "ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d" + ], + "maturity": "2021-02-04T00:00:00Z", + "descriptor": { + "base": 2, + "isSigned": false, + "unit": "BTC/USD", + "precision": 0 + }, + "eventId": "bitcoin-s-price-example" + } + } + } + }, + "fundingPubKey": "03a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33", + "payoutSPK": "1600148cd33b6fadc74aaca3982d3fd1891b1100a01e99", + "payoutSerialId": 7520084828858968064, + "offerCollateralSatoshis": 50000, + "fundingInputs": [ + { + "inputSerialId": 3740391543456242688, + "prevTx": "020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e83200000000", + "prevTxVout": 0, + "sequence": 4294967293, + "maxWitnessLen": 107, + "redeemScript": null + } + ], + "changeSPK": "16001404a16b09c5eba2e29899d2eaf5e9dde374be4940", + "changeSerialId": 3404283908717475840, + "fundOutputSerialId": 6109310038405377024, + "feeRatePerVb": 1, + "cetLocktime": 0, + "refundLocktime": 707177 +} +``` + +Now what Alice needs to send Bob her + +1. Offer +2. Tor address + +She can retrieve her tor address with + +``` +./bitcoin-s-cli getdlchostaddress +v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 +``` + +#### Accept + +Once Bob has received Alice's dlc host address and the offer, and reviews the terms of the offer with `decodeoffer`, he +can accept the offer. + +``` +./bitcoin-s-cli acceptdlc a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69 v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 + +``` + +Currently this RPC doesn't return anything, but if you look at logs you should see your funding tx broadcast. +You can find logs at `~/.bitcoin-s/{mainnet,testnet3,regtest}/bitcoin-s.log` + +``` +[info] 2021-10-15T21:21:11UTC INFO [DLCClient] connecting to SOCKS5 proxy localhost/127.0.0.1:65396 +[info] 2021-10-15T21:21:11UTC INFO [DLCClient] connected to SOCKS5 proxy localhost/127.0.0.1:65396 +[info] 2021-10-15T21:21:11UTC INFO [DLCClient] connecting to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 via SOCKS5 localhost/127.0.0.1:65396 +[info] 2021-10-15T21:21:48UTC INFO [DLCClient] connected to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 via SOCKS5 proxy localhost/127.0.0.1:65396 +[info] 2021-10-15T21:21:48UTC INFO [DLCDataHandler] Received LnMessage DLCOfferTLV +[info] 2021-10-15T21:21:48UTC INFO [DLCWallet$DLCWalletImpl] Initializing DLC from received offer with tempContractId acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e +[info] 2021-10-15T21:21:48UTC INFO [HikariDataSource] bitcoin-s.dlc.db - Starting... +[info] 2021-10-15T21:21:48UTC INFO [HikariDataSource] bitcoin-s.dlc.db - Start completed. +[info] 2021-10-15T21:21:48UTC INFO [DLCWallet$DLCWalletImpl] Creating DLC Accept for tempContractId acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e +[info] 2021-10-15T21:21:49UTC INFO [DLCWallet$DLCWalletImpl] Spending UTXOs: 91de6518fbf9eb656d9690224655049f5f21ac1c2189a142b1e0ce586989740d:2 +[info] 2021-10-15T21:21:49UTC INFO [DLCWallet$DLCWalletImpl] UTXO 0 details: TransactionOutput(4426788 sats,wpkh(7532253f570665ff9af4b53bcac49351f8236c84)) +[info] 2021-10-15T21:21:49UTC INFO [DLCWallet$DLCWalletImpl] Creating CET Sigs for fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:21:50UTC INFO [DLCWallet$DLCWalletImpl] Created DLCAccept for tempContractId acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e with contract Id fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:22:07UTC INFO [DLCDataHandler] Received LnMessage DLCSignTLV +[info] 2021-10-15T21:22:07UTC INFO [DLCWallet$DLCWalletImpl] Verifying CET Signatures for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:22:09UTC INFO [DLCWallet$DLCWalletImpl] CET Signatures are valid for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:22:09UTC INFO [DLCWallet$DLCWalletImpl] Verifying 1 funding sigs for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:22:11UTC INFO [DLCWallet$DLCWalletImpl] DLC fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 sigs are verified and stored, ready to broadcast +[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Created funding transaction 5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Broadcasting funding transaction 5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 +[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Adding UTXO to wallet: 6f61f256bceb3a3d987b29246c012090943365d0b0eb82c88d62ca0f8ea89650:2 amt=4376577 sats +[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Successfully inserted UTXO 6f61f256bceb3a3d987b29246c012090943365d0b0eb82c88d62ca0f8ea89650:2 into DB +[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Processing tx 5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f for 1 DLC(s) +``` + +You can check the state of the DLC with `getdlcs` + +``` +./bitcoin-s-cli getdlcs +[ + { + "state": "Broadcasted", + "dlcId": "543249d7c34014a774810d3633fb7d19f339fbcd4e88ceccad7018fa7b611706", + "isInitiator": false, + "lastUpdated": "2021-10-15T21:22:12.149Z", + "tempContractId": "acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e", + "contractId": "fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701", + "contractInfo": "fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65", + "contractMaturity": 706169, + "contractTimeout": 707177, + "feeRate": 1, + "totalCollateral": 100000, + "localCollateral": 50000, + "remoteCollateral": 50000, + "fundingTxId": "5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f" + } +] +``` + +You can find things like the `fundingTxId`, `state`, `dlcId`, and `contractId` from this RPC call. Since we just +broadcast the funding transaction, the state of the DLC is `Broadcast`. \ No newline at end of file diff --git a/website/versioned_docs/version-1.8.0/wallet/wallet.md b/website/versioned_docs/version-1.8.0/wallet/wallet.md new file mode 100644 index 0000000000..5944b44d8e --- /dev/null +++ b/website/versioned_docs/version-1.8.0/wallet/wallet.md @@ -0,0 +1,138 @@ +--- +title: Wallet +id: version-1.8.0-wallet +original_id: wallet +--- + +## Bitcoin-s wallet +Bitcoin-s comes bundled with a rudimentary Bitcoin wallet. This wallet +is capable of managing private keys, generating addresses, constructing +and signing transactions, among other things. It is BIP32/BIP44/BIP49/BIP84 +compatible. + +This wallet is currently only released as a library, and not as a binary. +This is because it (nor the documentation) is not deemed production +ready. Use at your own risk, and without too much money depending on it. + +### How is the bitcoin-s wallet implemented + +The bitcoin-s wallet is a scalable way for individuals up to large bitcoin exchanges to safely and securely store their bitcoin in a scalable way. + +All key interactions are delegated to the [key-manager](../key-manager/key-manager.md) which is a minimal dependency library to store and use key material. + +By default, we store the encrypted root key in `$HOME/.bitcoin-s/seeds/encrypted-bitcoin-s-seed.json`. This is the seed that is used for each of the wallets on each bitcoin network. +Multiple wallet seeds can be saved using the `bitcoin-s.wallet.walletName` config option. +You can read more in the [key manager docs](../key-manager/server-key-manager.md). + +The wallet itself is used to manage the utxo life cycle, create transactions, and update wallet balances to show how much money you have the on a bitcoin network. + +We use [slick](https://scala-slick.org/doc/3.3.1/) as middleware to support different database types. Depending on your use case, you can use something as simple as sqlite, or something much more scalable like postgres. + + +### Example + +This guide shows how to create a Bitcoin-s wallet and then +peer it with a `bitcoind` instance that relays +information about what is happening on the blockchain +through the P2P network. + +This is useful if you want more flexible signing procedures in +the JVM ecosystem and more granular control over your +UTXOs with popular database like Postgres, SQLite, etc. + +This code snippet you have a running `bitcoind` instance, locally +on regtest. + + +```scala +implicit val ec = scala.concurrent.ExecutionContext.global +implicit val system = ActorSystem("System") + +val config = ConfigFactory.parseString { + """ + | bitcoin-s { + | network = regtest + | } + """.stripMargin +} + + +val datadir = Files.createTempDirectory("bitcoin-s-wallet") + + +implicit val walletConfig = WalletAppConfig(datadir, config) + +// we also need to store chain state for syncing purposes +implicit val chainConfig = ChainAppConfig(datadir, config) + +// when this future completes, we have +// created the necessary directories and +// databases for managing both chain state +// and wallet state +val configF: Future[Unit] = for { + _ <- walletConfig.start() + _ <- chainConfig.start() +} yield () + +val bitcoindInstance = BitcoindInstanceLocal.fromDatadir() + +val bitcoind = BitcoindRpcClient(bitcoindInstance) + +// when this future completes, we have +// synced our chain handler to our bitcoind +// peer +val syncF: Future[ChainApi] = configF.flatMap { _ => + val getBestBlockHashFunc = { () => + bitcoind.getBestBlockHash + } + + + val getBlockHeaderFunc = { hash: DoubleSha256DigestBE => + bitcoind.getBlockHeader(hash).map(_.blockHeader) + } + + val blockHeaderDAO = BlockHeaderDAO() + val compactFilterHeaderDAO = CompactFilterHeaderDAO() + val compactFilterDAO = CompactFilterDAO() + val chainHandler = ChainHandler( + blockHeaderDAO, + compactFilterHeaderDAO, + compactFilterDAO, + blockFilterCheckpoints = Map.empty) + + ChainSync.sync(chainHandler, getBlockHeaderFunc, getBestBlockHashFunc) +} + +// once this future completes, we have a initialized +// wallet +val wallet = Wallet(new NodeApi { + override def broadcastTransactions(txs: Vector[Transaction]): Future[Unit] = Future.successful(()) + override def downloadBlocks(blockHashes: Vector[DoubleSha256Digest]): Future[Unit] = Future.successful(()) + }, chainApi, ConstantFeeRateProvider(SatoshisPerVirtualByte.one)) +val walletF: Future[WalletApi] = configF.flatMap { _ => + Wallet.initialize(wallet, None) +} + +// when this future completes, ww have sent a transaction +// from bitcoind to the Bitcoin-S wallet +val transactionF: Future[(Transaction, Option[DoubleSha256DigestBE])] = for { + wallet <- walletF + address <- wallet.getNewAddress() + txid <- bitcoind.sendToAddress(address, 3.bitcoin) + transaction <- bitcoind.getRawTransaction(txid) +} yield (transaction.hex, transaction.blockhash) + +// when this future completes, we have processed +// the transaction from bitcoind, and we have +// queried our balance for the current balance +val balanceF: Future[CurrencyUnit] = for { + wallet <- walletF + (tx, blockhash) <- transactionF + _ <- wallet.processTransaction(tx, blockhash) + balance <- wallet.getBalance() +} yield balance + +balanceF.foreach { balance => + println(s"Bitcoin-S wallet balance: $balance") +} +```