mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-22 14:33:06 +01:00
Add missing markdown files (#3779)
This commit is contained in:
parent
403c78fd8f
commit
c5c76ea46b
12 changed files with 2394 additions and 0 deletions
171
website/versioned_docs/version-1.8.0/chain/chain-query-api.md
Normal file
171
website/versioned_docs/version-1.8.0/chain/chain-query-api.md
Normal file
|
@ -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)
|
||||
```
|
77
website/versioned_docs/version-1.8.0/chain/chain.md
Normal file
77
website/versioned_docs/version-1.8.0/chain/chain.md
Normal file
|
@ -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}")
|
||||
}
|
||||
```
|
83
website/versioned_docs/version-1.8.0/node/node-api.md
Normal file
83
website/versioned_docs/version-1.8.0/node/node-api.md
Normal file
|
@ -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))
|
||||
```
|
|
@ -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"
|
||||
}
|
||||
```
|
|
@ -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
|
||||
]
|
||||
}
|
||||
```
|
195
website/versioned_docs/version-1.8.0/oracle/oracle-server.md
Normal file
195
website/versioned_docs/version-1.8.0/oracle/oracle-server.md
Normal file
|
@ -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` - <b>WARNING THIS CAN LEAD TO DLCs NOT SETTLING IF USERS HAVE BUILT DLCS OFF OF THIS ANNOUNCEMENT. USE WITH CARE.</b>
|
||||
- `name` - Name for this event
|
||||
- `deleteattestation` `name` - <b>WARNING THIS CAN LEAD TO PRIVATE KEY LEAK IF YOU SIGN ANOTHER ATTESTATION AFTER DELETING A PREVIOUS ONE. USE WITH CARE.</b>
|
||||
- `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}
|
||||
```
|
133
website/versioned_docs/version-1.8.0/rpc/bitcoind.md
Normal file
133
website/versioned_docs/version-1.8.0/rpc/bitcoind.md
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
||||
```
|
173
website/versioned_docs/version-1.8.0/testkit/testkit.md
Normal file
173
website/versioned_docs/version-1.8.0/testkit/testkit.md
Normal file
|
@ -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.
|
322
website/versioned_docs/version-1.8.0/wallet/dlc.md
Normal file
322
website/versioned_docs/version-1.8.0/wallet/dlc.md
Normal file
|
@ -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]
|
||||
```
|
|
@ -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/<unresolved>:2862 via SOCKS5 localhost/127.0.0.1:49196
|
||||
[info] 2021-10-03T21:03:02UTC INFO [DLCClient] connected to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion/<unresolved>: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:
|
|
@ -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`.
|
138
website/versioned_docs/version-1.8.0/wallet/wallet.md
Normal file
138
website/versioned_docs/version-1.8.0/wallet/wallet.md
Normal file
|
@ -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")
|
||||
}
|
||||
```
|
Loading…
Add table
Reference in a new issue