1.9.2 website (#4390)

This commit is contained in:
Chris Stewart 2022-06-14 11:47:20 -05:00 committed by GitHub
parent 52ded677e0
commit 678c29cf81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 3039 additions and 0 deletions

View file

@ -1021,6 +1021,57 @@
},
"version-1.9.1/wallet/version-1.9.1-wallet-rpc": {
"title": "Wallet RPC Examples"
},
"version-1.9.2/applications/version-1.9.2-cli": {
"title": "CLI"
},
"version-1.9.2/applications/version-1.9.2-server": {
"title": "Application Server"
},
"version-1.9.2/chain/version-1.9.2-chain-query-api": {
"title": "Chain Query API"
},
"version-1.9.2/core/version-1.9.2-addresses": {
"title": "Generating Addresses"
},
"version-1.9.2/core/version-1.9.2-dlc": {
"title": "Discreet Log Contract Data Structures"
},
"version-1.9.2/core/version-1.9.2-hd-keys": {
"title": "HD Key Generation"
},
"version-1.9.2/core/version-1.9.2-txbuilder": {
"title": "TxBuilder Example"
},
"version-1.9.2/crypto/version-1.9.2-sign": {
"title": "Sign API"
},
"version-1.9.2/version-1.9.2-getting-started": {
"title": "Intro and Getting Started"
},
"version-1.9.2/key-manager/version-1.9.2-key-manager": {
"title": "Key Manager"
},
"version-1.9.2/node/version-1.9.2-node-api title: Node API": {
"title": "node-api title: Node API"
},
"version-1.9.2/oracle/version-1.9.2-oracle-server": {
"title": "Oracle Server"
},
"version-1.9.2/secp256k1/version-1.9.2-secp256k1": {
"title": "Secp256k1"
},
"version-1.9.2/version-1.9.2-security": {
"title": "Security"
},
"version-1.9.2/version-1.9.2-ui-setup": {
"title": "Installing the DLC Wallet UI"
},
"version-1.9.2/wallet/version-1.9.2-wallet-election-example": {
"title": "Wallet Election Example"
},
"version-1.9.2/wallet/version-1.9.2-wallet-price-example": {
"title": "Wallet Price Example"
}
},
"links": {

View file

@ -0,0 +1,64 @@
---
id: version-1.9.2-cli
title: CLI
original_id: cli
---
## Bitcoin-s command line interface
The [cli](/api/org/bitcoins/cli) project is meant to be a bitcoin-s command line interface (cli).
You only need to do one of the two sections below (Building the command line interface) or (Native binaries), and we recommend doing the first option because it is simpler.
### Building the command line interface
You must first have [bitcoin-s properly installed](../getting-setup) on your machine, after which you should be able to build the cli with
```bashrc
sbt cli/universal:stage
```
After running that command you should find the executable here:
```bash
./app/cli/target/universal/stage/bin/bitcoin-s-cli
```
### Executing commands
You can ask the client for help with
```bash
./app/cli/target/universal/stage/bin/bitcoin-s-cli --help
Usage: bitcoin-s-cli [options] [<cmd>]
-n, --network <value> Select the active network.
--debug Print debugging information
-h, --help Display this help message and exit
<cmd> The command and arguments to be executed. Try bitcoin-s-cli help for a list of all commands
```
Now you are are ready to start the server that the cli sends commands to. Take a look at our [server](server.md) documentation on how to build and start the server.
### Native binaries
Bitcoin-s also supports building native executables for various platforms supported by the [graalvm native image](https://www.graalvm.org/reference-manual/native-image/) tool.
You can build by using the [native image plugin for sbt](https://github.com/scalameta/sbt-native-image). This will download the appropriate graalvm
version and the native image tool, and then build the cli
```bashrc
sbt cli/nativeImage
```
After the build is done, you can find the artifact here locally
```bashrc
app/cli/target/native-image/bitcoin-s-cli
```
We also publish native image binaries every time we merge a commit to master on github.
As an example, you can [see the artifacts](https://github.com/bitcoin-s/bitcoin-s/actions?query=workflow%3A%22Native+Image+bitcoin-s-cli%22)
in the upper right hand corner.
If you don't want to build the `bitcoin-s-cli` yourself, you can download it for your platform there.

View file

@ -0,0 +1,399 @@
---
id: version-1.9.2-server
title: Application Server
original_id: server
---
## App server
The server project is the aggregation of these three sub projects
1. [Wallet](../wallet/wallet.md)
2. [Chain](../chain/chain.md)
3. [Node](../node/node.md)
The server project provides a away to access information from these three projects via a JSON RPC.
## Building the server
### Java binary
You can build the server with the [sbt native packager](https://github.com/sbt/sbt-native-packager).
The native packager offers [numerous ways to package the project](https://github.com/sbt/sbt-native-packager#examples).
In this example we are going to use `stage` which will produce bash scripts we can easily execute. You can stage the server with the following command.
```bash
sbt appServer/universal:stage
```
This will produce a script to execute bitcoin-s which you can start with
```bash
./app/server/target/universal/stage/bin/bitcoin-s-server
```
### Docker
The oracle server also has docker support. You can build a docker image with the following commands
#### Using an existing docker image
We publish docker images on every PR that is merged to bitcoin-s.
You can find the docker repo for the app server [here](https://hub.docker.com/r/bitcoinscala/bitcoin-s-server/tags?page=1&ordering=last_updated)
#### Building a docker image
```
sbt "appServer/docker:stage"
```
This will build a `Dockerfile` that is located in `app/server/target/docker/stage`
You can now build the docker image with
```
docker build app/server/target/docker/stage/ -t bitcoinscala/bitcoin-s-server:latest
```
Finally, let's run the image! It's important that you correctly configure port forwarding with the docker container so
you can interact with the running container with `bitcoin-s-cli` or `curl`. By default, our oracle
server listens for requests on port `9999`. By default, the server listens for websocket connections on port `19999` at `/events`.
This means we need to forward requests on the host machine to the docker container correctly.
This can be done with the following command
```
docker run -d -p 9999:9999 -p 19999:19999 -e BITCOIN_S_SERVER_RPC_PASSWORD='topsecret' bitcoinscala/bitcoin-s-server:latest
```
Now you can send requests with `bitcoin-s-cli` or `curl`.
Here is an example with `bitcoin-s-cli`
```
./bitcoin-s-cli getblockcount --password topsecret
10000
```
For more information on build configuration options with `sbt` please see the [sbt native packager docs](https://sbt-native-packager.readthedocs.io/en/latest/formats/docker.html#tasks)
## Configuration
### Java binary configuration
If you would like to pass in a custom datadir for your server, you can do
```bash
./app/server/target/universal/stage/bin/bitcoin-s-server --datadir /path/to/datadir/
```
To use a config file that is not the `bitcoin-s.conf` file in your datadir, you can do
```bash
./app/server/target/universal/stage/bin/bitcoin-s-server --conf /path/to/file.conf
```
You can also pass in a custom `rpcport` to bind to
```bash
./app/server/target/universal/stage/bin/bitcoin-s-server --rpcport 12345
```
Or set a custom `wsport` to bind to
```bash
./app/server/target/universal/stage/bin/bitcoin-s-server --wsport 54321
```
For more information on configuring the server please see our [configuration](../config/configuration.md) document
For more information on how to use our built in `cli` to interact with the server please see [cli.md](cli.md)
### Docker configuration
In this example, we are using the latest docker image published to our [docker hub](https://hub.docker.com/repository/docker/bitcoinscala/bitcoin-s-oracle-server/tags?page=1&ordering=last_updated)
which is referenced by `bitcoinscala/bitcoin-s-server:latest`
You can use bitcoin-s with docker volumes. You can also pass in a custom configuration at container runtime.
#### Using a docker volume
```basrc
docker volume create bitcoin-s
docker run -p 9999:9999 -p 19999:19999 \
--mount source=bitcoin-s,target=/home/bitcoin-s/ bitcoinscala/bitcoin-s-server:latest
```
Now you can re-use this volume across container runs. It will keep the same oracle database
and seeds directory located at `/home/bitcoin-s/.bitcoin-s/seeds` in the volume.
#### Using a custom bitcoin-s configuration with docker
You can also specify a custom bitcoin-s configuration at container runtime.
You can mount the configuration file on the docker container and that
configuration will be used in the docker container runtime rather than
the default one we provide [here](https://github.com/bitcoin-s/bitcoin-s/blob/master/app/oracle-server/src/universal/docker-application.conf)
You can do this with the following command
```bashrc
docker run -p 9999:9999 -p 19999:19999 \
--mount type=bind,source=/my/new/config/,target=/home/bitcoin-s/.bitcoin-s/ \
bitcoinscala/bitcoin-s-server:latest --conf /home/bitcoin-s/.bitcoin-s/bitcoin-s.conf
```
Note: If you adjust the `bitcoin-s.server.rpcport` setting you will need to adjust
the `-p 9999:9999` port mapping on the docker container to adjust for this.
## Server Endpoints
### Common
- `getversion` - The version of our application you are using
- `zipdatadir` `location` - Backs up the datadir in a safe and consistent manner.
- `location` - The locations of the backup zip
### Blockchain
- `getblockcount` - Get the current block height
- `getfiltercount` - Get the number of filters
- `getfilterheadercount` - Get the number of filter headers
- `getbestblockhash` - Get the best block hash
- `getblockheader` - Returns information about block header <hash>
- `hash` - The block hash
- `decoderawtransaction` `tx` - `Decode the given raw hex transaction`
- `tx` - Transaction encoded in hex to decode
- `getmediantimepast` - Returns the median time past
### Wallet
- `rescan` `[options]` - Rescan for wallet UTXOs
- `--force` - Clears existing wallet records. Warning! Use with caution!
- `--batch-size <value>` - Number of filters that can be matched in one batch
- `--start <value>` - Start height
- `--end <value>` - End height
- `--ignorecreationtime` - Ignores the wallet creation date and will instead do a full rescan
- `isempty` - Checks if the wallet contains any data
- `walletinfo` - Returns data about the current wallet being used
- `getbalance` `[options]` - Get the wallet balance
- `--sats ` - Display balance in satoshis
- `getconfirmedbalance` `[options]` - Get the wallet balance of confirmed utxos
- `--sats ` - Display balance in satoshis
- `getunconfirmedbalance` `[options]` - Get the wallet balance of unconfirmed utxos
- `--sats ` - Display balance in satoshis
- `getbalances` `[options]` - Get the wallet balance by utxo state
- `--sats ` - Display balance in satoshis
- `getutxos` - Returns list of all wallet utxos
- `getaddresses` - Returns list of all wallet addresses currently being watched
- `getspentaddresses` - Returns list of all wallet addresses that have received funds and been spent
- `getfundedaddresses` - Returns list of all wallet addresses that are holding funds
- `getunusedaddresses` - Returns list of all wallet addresses that have not been used
- `getaccounts` - Returns list of all wallet accounts
- `walletinfo` - Returns meta information about the wallet
- `createnewaccount` - Creates a new wallet account
- `getaddressinfo` `address` - Returns list of all wallet accounts
- `address` - Address to get information about
- `getnewaddress` - Get a new address
- `listreservedutxos` - lists all utxos that are reserved in the wallet
- `sendtoaddress` `address` `amount` `[options]` - Send money to the given address
- `address` - Address to send to
- `amount` - Amount to send in BTC
- `--feerate <value>` - Fee rate in sats per virtual byte
- `sendfromoutpoints` `outpoints` `address` `amount` `[options]` - Send money to the given address
- `outpoints` - Out Points to send from
- `address` - Address to send to
- `amount` - Amount to send in BTC
- `--feerate <value>` - Fee rate in sats per virtual byte
- `sweepwallet` `address` `[options]` - Sends the entire wallet balance to the given address
- `address` - Address to send to
- `--feerate <value>` - Fee rate in sats per virtual byte
- `sendwithalgo` `address` `amount` `algo` `[options]` - Send money to the given address using a specific coin selection algo
- `address` - Address to send to
- `amount` - Amount to send in BTC
- `algo` - Coin selection algo
- `--feerate <value>` - Fee rate in sats per virtual byte
- `signpsbt` `psbt` - Signs the PSBT's inputs with keys that are associated with the wallet
- `psbt` - PSBT to sign
- `opreturncommit` `message` `[options]` - Creates OP_RETURN commitment transaction
- `message` - message to put into OP_RETURN commitment
- `--hashMessage` - should the message be hashed before commitment
- `--feerate <value>` - Fee rate in sats per virtual byte
- `bumpfeecpfp` `txid` `feerate` - Bump the fee of the given transaction id with a child tx using the given fee rate
- `txid` - Id of transaction to bump fee
- `feerate` - Fee rate in sats per virtual byte of the child transaction
- `bumpfeerbf` `txid` `feerate` - Replace given transaction with one with the new fee rate
- `txid` - Id of transaction to bump fee
- `feerate` - New fee rate in sats per virtual byte
- `gettransaction` `txid` - Get detailed information about in-wallet transaction <txid>
- `txid` - The transaction id
- `lockunspent` `unlock` `transactions` - Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.
- `unlock` - Whether to unlock (true) or lock (false) the specified transactions
- `transactions` - The transaction outpoints to unlock/lock, empty to apply to all utxos
- `importseed` `walletname` `words` `passphrase` - Imports a mnemonic seed as a new seed file
- `walletname` - Name to associate with this seed
- `words` - Mnemonic seed words, space separated
- `passphrase` - Passphrase to encrypt this seed with
- `importxprv` `walletname` `xprv` `passphrase` - Imports a mnemonic seed as a new seed file
- `walletname` - Name to associate with this seed
- `xprv` - base58 encoded extended private key
- `passphrase` - Passphrase to encrypt this seed with
- `keymanagerpassphrasechange` `oldpassphrase` `newpassphrase` - Changes the wallet passphrase
- `oldpassphrase` - The current passphrase
- `newpassphrase` - The new passphrase
- `keymanagerpassphraseset` `passphrase` - Encrypts the wallet with the given passphrase
- `passphrase` - The passphrase to encrypt the wallet with
### DLC
- `createcontractinfo` `announcement` `totalCollateral` `payouts`
- the announcement to build the contract info for
- the total amount of collateral in the DLC
- The payouts can be in two formats
1. `{ "outcomes" : { "outcome0" : 0, "outcome1": 1, ... }}`. The number is the amount of sats paid to YOU for that outcome.
2. `[{"outcome":0,"payout":0,"extraPrecision":0,"isEndpoint":true}, {"outcome":1,"payout":1,"extraPrecision":0,"isEndpoint":true}, ...]`
- `decodecontractinfo` `contractinfo` - Decodes a contract info into json
- `contractinfo` - Hex encoded contract info
- `decodeoffer` `offer` - Decodes an offer message into json
- `offer` - Hex encoded dlc offer message
- `decodeaccept` `accept` - Decodes an accept message into json
- `accept` - Hex encoded dlc accept message
- `decodesign` `sign` - Decodes a sign message into json
- `sign` - Hex encoded dlc sign message
- `decodeannouncement` `announcement` - Decodes an oracle announcement message into json
- `announcement` - Hex encoded oracle announcement message
- `decodeattestments` `attestments` - Decodes an oracle attestments message into json
- `attestments` - Hex encoded oracle attestments message
- `getdlchostaddress` - Returns the public listening address of the DLC Node
- `createdlcoffer` `contractInfo` `collateral` `[feerate]` `refundlocktime` `[options]` - Creates a DLC offer that another party can accept
- `contractInfo` - Hex encoded contractInfo message
- `collateral` - Satoshis to fund your side of the DLC
- `feerate` - Fee rate for both funding and closing transactions, in sats/vbytes
- `refundlocktime` - Locktime of the refund transaction
- `cetlocktime <value>` - Should not be set unless you know what you are doing. Locktime of the contract execution transactions (defaults to current height)
- `peer` - Peer's network address
- `acceptdlc` `offer` `peer` - Accepts a DLC offer given from another party
- `offer` - Hex encoded dlc offer message
- `peer` - Peer's network address
- `acceptdlcoffer` `offer` - Accepts a DLC offer given from another party
- `offer` - Hex encoded offer message
- `peer` - Peer's network address
- `acceptdlcofferfromfile` `path` `[destination]` - Accepts a DLC offer given from another party
- `path` - Path to dlc offer file
- `destination` - Path to write dlc accept message
- `contact-add` `alias` `address` `memo`
- `alias` - alias for the address like a name
- `address` - the tor address for the peer
- `memo` - a memo for this contact
- `contacts-list` - lists all contacts in the wallet
- `contact-remove` `address`
- `address` - the tor address for the peer to remove
- `dlc-contact-add` `dlcid` `address` - Associated a DLC with a peer
- `dlc-contact-remove` `dlcid` - Removes a DLC-peer association
- `address` - the tor address for the peer to remove
- `signdlc` `accept` - Signs a DLC
- `accept` - Hex encoded dlc accept message
- `signdlcfromfile` `path` `[destination]` - Signs a DLC
- `path` - Path to dlc accept file
- `destination` - Path to write dlc sign message
- `adddlcsigs` `sigs` - Adds DLC Signatures into the database
- `sigs` - Hex encoded dlc sign message
- `adddlcsigsfromfile` `path` - Adds DLC Signatures into the database
- `path` - Path to dlc sign file
- `adddlcsigsandbroadcast` `sigs` - Adds DLC Signatures into the database and broadcasts the funding transaction
- `sigs` - Hex encoded dlc sign message
- `adddlcsigsandbroadcastfromfile` `path` - Adds DLC Signatures into the database and broadcasts the funding transaction
- `path` - Path to dlc sign file
- `getdlcfundingtx` `contractId` - Returns the Funding Tx corresponding to the DLC with the given contractId
- `contractId` - ContractId of the DLC
- `broadcastdlcfundingtx` `contractId` - Broadcasts the funding Tx corresponding to the DLC with the given contractId
- `contractId` - ContractId of the DLC
- `executedlc` `contractId` `oraclesigs` `[options]` - Executes the DLC with the given contractId
- `contractId` - ContractId of the DLC
- `oraclesigs` - Array of oracle attestations
- `--noBroadcast` - Gives full serialized transaction instead of broadcasting
- `executedlcrefund` `contractId` `[options]` - Executes the Refund transaction for the given DLC
- `contractId` - ContractId of the DLC
- `--noBroadcast` - Gives full serialized transaction instead of broadcasting
- `canceldlc` `dlcId` - Cancels a DLC and unreserves used utxos
- `dlcId` - Internal id of the DLC
- `getdlcs` - Returns all dlcs in the wallet
- `address` - optional contact address, if specified the RPC returns only DLCs associated with the given address
- `getdlc` `dlcId` - Gets a specific dlc in the wallet
- `dlcId` - Internal id of the DLC
- `offer-add` `offerTLV` `peerAddress` `message` - Puts an incoming offer into the inbox
- `offerTLV` - Offer TLV
- `peer` - Peer URI (optional)
- `message` - Peer's message or note (optional)
- `"offer-remove` `hash` - Remove an incoming offer from inbox
- `hash` - Hash of the offer TLV
- `offer-send` `offerOrTempContractId` `peerAddress` `message` - Sends an offer to a peer. `offerOrTempContractId` is either an offer TLV or a temporary contract ID.
- `offers-list` - List all incoming offers from the inbox
- `getdlcoffer` `tempContractId` - Gets a DLC offer by temporary contract ID.
- `getaddresslabel` `address` - gets all labels for an address
- `getaddresslabels` - returns all addresses with labels in the wallet
- `dropaddresslabel` `address` `label` - drops the label for a given address
- `dropaddresslabels` `address` - drops all labels for the given address
### Network
- `getpeers` - List the connected peers
- `stop` - Request a graceful shutdown of Bitcoin-S
- `sendrawtransaction` `tx` `Broadcasts the raw transaction`
- `tx` - Transaction serialized in hex
### PSBT
- `decodepsbt` `psbt` - Return a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.
- `psbt` - PSBT serialized in hex or base64 format
- `combinepsbts` `psbts` - Combines all the given PSBTs
- `psbts` - PSBTs serialized in hex or base64 format
- `joinpsbts` `psbts` - Combines all the given PSBTs
- `psbts` - PSBTs serialized in hex or base64 format
- `finalizepsbt` `psbt` - Finalizes the given PSBT if it can
- `psbt` - PSBT serialized in hex or base64 format
- `extractfrompsbt` `psbt` - Extracts a transaction from the given PSBT if it can
- `psbt` - PSBT serialized in hex or base64 format
- `converttopsbt` `unsignedTx` - Creates an empty psbt from the given transaction
- `unsignedTx` - serialized unsigned transaction in hex
### Util
- `createmultisig` `nrequired` `keys` `[address_type]` - Creates a multi-signature address with n signature of m keys required.
- `nrequired` - The number of required signatures out of the n keys.
- `keys` - The hex-encoded public keys.
- `address_type` -The address type to use. Options are "legacy", "p2sh-segwit", and "bech32"
- `estimatefee` - Returns the recommended fee rate using the fee provider
## Sign PSBT with Wallet Example
Bitcoin-S CLI:
```bash
bitcoin-s-cli signpsbt cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA
cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA
```
CURL:
```bash
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signpsbt", "params": ["cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA"]}' -H "Content-Type: application/json" http://127.0.0.1:9999/
{"result":"cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA","error":null}
```
## Websocket endpoints
Bitcoin-s offers websocket endpoints. By default, the endpoint is `ws://localhost:1999/events`
You can configure where how the endpoints are configured inside your `bitcoin-s.conf`
```
bitcoin-s.server.wsbind=localhost
bitcoin-s.server.wsport=19999
```
These events are implemented using our [internal callback mechanism](../wallet/wallet-callbacks.md#wallet-callbacks).
An example event that is defined is our `blockprocess` event.
Everytime our wallet processes a block, our wallet will notify you via websockets.
Here is an example payload
The current types of events defined are
1. `txprocessed` - when the wallet processes a transaction. Every transaction in a block will get relayed currently
2. `reservedutxos` - when the wallet reserves OR unreserves utxos
3. `newaddress` - when the wallet generates a new address
4. `txbroadcast` - when the wallet broadcasts a tx
5. `blockprocessed` - when the wallet processes a block
```
{"type":"blockprocessed","payload":{"raw":"04e0ff2ffce8c3e866e367d305886a3f9d353e557524f61f9cf0c26c46000000000000001206d2e396387bff1c13cbe572d4646abae1ae405f4066ab5e6f5edd6d8f028008a8bb61ffff001af23dd47e","hash":"00000000000000de21f23f6945f028d5ecb47863428f6e9e035ab2fb7a3ef356","confirmations":1,"height":2131641,"version":805298180,"versionHex":"2fffe004","merkleroot":"80028f6ddd5e6f5eab66405f40aee1ba6a64d472e5cb131cff7b3896e3d20612","time":1639688200,"mediantime":1639688200,"nonce":2127838706,"bits":"1a00ffff","difficulty":1.6069135243303364E60,"chainwork":"00000000000000000000000000000000000000000000062438437ddd009e698b","previousblockhash":"00000000000000466cc2f09c1ff62475553e359d3f6a8805d367e366e8c3e8fc","nextblockhash":null}}
```

View file

@ -0,0 +1,175 @@
---
id: version-1.9.2-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]]
def getMedianTimePast(): Future[Long]
}
```
## 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.getNeutrinoTestConfig().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)
}
override def getMedianTimePast(): Future[Long] = bitcoind.getMedianTimePast()
}
// 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)
```

View file

@ -0,0 +1,59 @@
---
id: version-1.9.2-addresses
title: Generating Addresses
original_id: addresses
---
Almost all Bitcoin applications need to generate addresses
for their users somehow. There's a lot going on in getting
a correct bitcoin address, but our APIs make it possible to
to get started with all types of addresses in a matter of
minutes.
## Generating SegWit (bech32) addresses
Generating native SegWit addresses in the bech32 format
is something that all Bitcoin applications should enable,
as it makes the transaction fees less expensive, and also
makes the addresses more readable by humans. However, it
has seen slower than necessary adoption. With Bitcoin-S
you can generate bech32 addresses in four(!) lines of code
(not counting comments and imports), so now there's no
reason to keep using legacy transaction formats.
```scala
// this generates a random private key
val privkey = ECPrivateKey()
// privkey: ECPrivateKey = Masked(ECPrivateKey)
val pubkey = privkey.publicKey
// pubkey: org.bitcoins.crypto.ECPublicKey = ECPublicKey(0399dea3a0dad9e21812f94ad69262a94fd51a2ed2b1507928afce2a358907a2de)
val segwitAddress = {
// see https://bitcoin.org/en/glossary/pubkey-script
// for reading resources on the details of scriptPubKeys
// pay-to-witness-pubkey-hash scriptPubKey V0
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
Bech32Address(scriptPubKey, TestNet3)
}
// segwitAddress: Bech32Address = tb1qd5kg59zdpa7xqm3qnqwnuj7sxwzvx6axy8ncja
println(segwitAddress.toString)
// tb1qd5kg59zdpa7xqm3qnqwnuj7sxwzvx6axy8ncja
```
## Generating legacy (base58) addresses
If you need to generate legacy addresses for backwards
compatability reasons, that's also a walk in the park.
Take a look:
```scala
// we're reusing the same private/public key pair
// from before. don't do this in an actual application!
val legacyAddress = P2PKHAddress(pubkey, TestNet3)
// legacyAddress: P2PKHAddress = mqUDJcXeTYj9R2eU4ksu57UhNFtzAbeaYS
println(legacyAddress.toString)
// mqUDJcXeTYj9R2eU4ksu57UhNFtzAbeaYS
```

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,145 @@
---
id: version-1.9.2-hd-keys
title: HD Key Generation
original_id: hd-keys
---
In modern Bitcoin wallets, users only need to write down
a sequence of words, and that sequence is a complete backup
of their wallet. This is thanks to what's called Hierarchical
Deterministic key generation. In short, every wallet using HD
key generation has a root seed for each wallet, and this
seed can be used to generate an arbitrary amount of later
private and public keys. This is done in a standardized manner,
so different wallets can operate with the same standard.
> If you want to jump into the details of how this work,
> you should check out
> [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).
Bitcoin-S supports generating keys in this fashion. Here's a
full example of how to obtain a wallet seed, and then
use that to generate further private and public keys:
```scala
import scodec.bits._
import org.bitcoins.core.crypto._
import org.bitcoins.core.hd._
// the length of the entropy bit vector determine
// how long our phrase ends up being
// 256 bits of entropy results in 24 words
val entropy: BitVector = MnemonicCode.getEntropy256Bits
// entropy: BitVector = BitVector(256 bits, 0x2c3bfad990775c8e1f1c0be259d97a5c06965922f1a5e2502dbbdb4dd1da574d)
val mnemonicCode = MnemonicCode.fromEntropy(entropy)
// mnemonicCode: MnemonicCode = Masked(MnemonicCodeImpl)
mnemonicCode.words // the phrase the user should write down
// res0: Vector[String] = Vector(club, thank, reopen, can, into, either, ladder, lift, time, solution, future, retreat, harvest, clutch, mesh, cruise, time, lift, humble, repair, tackle, unfold, frog, pave) // the phrase the user should write down
// the password argument is an optional, extra security
// measure. all MnemonicCode instances will give you a
// valid BIP39 seed, but different passwords will give
// you different seeds. So you could have as many wallets
// from the same seed as you'd like, by simply giving them
// different passwords.
val bip39Seed = BIP39Seed.fromMnemonic(mnemonicCode,
password = "secret password")
// bip39Seed: BIP39Seed = Masked(BIP39SeedImpl)
val xpriv = ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.SegWitMainNetPriv,
bip39Seed)
// xpriv: ExtPrivateKey = Masked(ExtPrivateKeyImpl)
val xpub = xpriv.extPublicKey
// xpub: ExtPublicKey = zpub6jftahH18ngZwEWTZuNHbNgJ39b2sdz5sMXKRv5pXbugPn2b4frQfi7P97CwqRRYmL6PmAC1erwFRMJf66oE64vdmkR3QW4bsxrotEoGKkh
// you can now use the generated xpriv to derive further
// private or public keys
// this can be done with BIP89 paths (called SegWitHDPath in bitcoin-s)
val segwitPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
// segwitPath: SegWitHDPath = m/84'/0'/0'/0/0
// alternatively:
val otherSegwitPath =
SegWitHDPath(HDCoinType.Bitcoin,
accountIndex = 0,
HDChainType.External,
addressIndex = 0)
// otherSegwitPath: SegWitHDPath = m/84'/0'/0'/0/0
segwitPath == otherSegwitPath
// res1: Boolean = true
```
## Generating new addresses without having access to the private key
One the coolest features of HD wallets is that it's possible
to generate addresses offline, without having access to the
private keys. This feature is commonly called watch-only
wallets, where a wallet can import information about all
your past and future transactions, without being able to
spend or steal any of your money.
Let's see an example of this:
```scala
import scala.util.Success
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.Bech32Address
import org.bitcoins.core.config.TestNet3
// first account -------┐
// bitcoin ----------┐ |
// segwit --------┐ | |
val accountPath = BIP32Path.fromString("m/84'/0'/0'")
// accountPath: BIP32Path = m/84'/0'/0'
val accountXpub = {
// this key is sensitive, keep away from prying eyes!
val accountXpriv = xpriv.deriveChildPrivKey(accountPath)
// this key is not sufficient to spend from, but we
// can generate addresses with it!
accountXpriv.extPublicKey
}
// accountXpub: ExtPublicKey = zpub6qnQJzSgN1NaJp5kPY7DPbc3joQ7Fw6vkdTCBtwKdsBTxpLECH84qv85LnsPLq3eVKnopY1b4PNBADWCmQs4SxvPbm7iwvkafk2miN8vGhx
// address no. 0 ---------------┐
// external address ----------┐ |
val firstAddressPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
// firstAddressPath: SegWitHDPath = m/84'/0'/0'/0/0
val firstAccountAddress = {
// this is a bit quirky, but we're not interesting in
// deriving the complete path from our account xpub
// instead, we're only interested in the part after
// the account level (3rd level). the .diff() method
// achieves that
val Some(pathDiff) = accountPath.diff(firstAddressPath)
// deriving public keys from hardened extended keys
// is not possible, that's why .deriveChildPubKey()
// returns a Try[ExtPublicKey]. A hardened key is marked
// by a ' after the number in the notation we use above.
val Success(extPubKey) = accountXpub.deriveChildPubKey(pathDiff)
val pubkey = extPubKey.key
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
Bech32Address(scriptPubKey, TestNet3)
}
// firstAccountAddress: Bech32Address = tb1qv32jwzqxyfqz6mss4z9kvq6pnye0chvqpm3a24
// tada! We just generated an address you can send money to,
// without having access to the private key!
firstAccountAddress.value
// res2: String = tb1qv32jwzqxyfqz6mss4z9kvq6pnye0chvqpm3a24
// you can now continue deriving addresses from the same public
// key, by imitating what we did above. To get the next
// HD path to generate an address at:
val nextAddressPath: SegWitHDPath = firstAddressPath.next
// nextAddressPath: SegWitHDPath = m/84'/0'/0'/0/1
```
### Signing things with HD keys
Please see [sign.md](../crypto/sign.md) for information on how to sign things with HD keys.

View file

@ -0,0 +1,158 @@
---
id: version-1.9.2-txbuilder
title: TxBuilder Example
original_id: txbuilder
---
Bitcoin-S features a transaction building API that allows you to construct and sign Bitcoin transactions. Here's an example of how to use it
```scala
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
// ec: ExecutionContext = scala.concurrent.impl.ExecutionContextImpl$$anon$3@7081ff47[Running, parallelism = 16, size = 0, active = 0, running = 0, steals = 0, tasks = 0, submissions = 0]
// Initialize a transaction builder
val builder = RawTxBuilder()
// builder: RawTxBuilder = RawTxBuilder()
// generate a fresh private key that we are going to use in the scriptpubkey
val privKey = ECPrivateKey.freshPrivateKey
// privKey: ECPrivateKey = Masked(ECPrivateKey)
val pubKey = privKey.publicKey
// pubKey: ECPublicKey = ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)
// this is the script that the TxBuilder is going to create a
// script signature that validly spends this scriptPubKey
val creditingSpk = P2PKHScriptPubKey(pubKey = privKey.publicKey)
// creditingSpk: P2PKHScriptPubKey = pkh(7484de8aafb35f3f70b2d50128055867e1f746ec)
val amount = 10000.satoshis
// amount: Satoshis = 10000 sats
// this is the UTXO we are going to be spending
val utxo =
TransactionOutput(value = amount, scriptPubKey = creditingSpk)
// utxo: TransactionOutput = TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))
// the private key that locks the funds for the script we are spending too
val destinationPrivKey = ECPrivateKey.freshPrivateKey
// destinationPrivKey: ECPrivateKey = Masked(ECPrivateKey)
// the amount we are sending -- 5000 satoshis -- to the destinationSPK
val destinationAmount = 5000.satoshis
// destinationAmount: Satoshis = 5000 sats
// the script that corresponds to destination private key, this is what is receiving the money
val destinationSPK =
P2PKHScriptPubKey(pubKey = destinationPrivKey.publicKey)
// destinationSPK: P2PKHScriptPubKey = pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)
// this is where we are sending money too
// we could add more destinations here if we
// wanted to batch transactions
val destinations = {
val destination0 = TransactionOutput(value = destinationAmount,
scriptPubKey = destinationSPK)
Vector(destination0)
}
// destinations: Vector[TransactionOutput] = Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)))
// Add the destinations to the tx builder
builder ++= destinations
// res0: RawTxBuilder = RawTxBuilder()
// we have to fabricate a transaction that contains the
// UTXO we are trying to spend. If this were a real blockchain
// we would need to reference the UTXO set
val creditingTx = BaseTransaction(version = Int32.one,
inputs = Vector.empty,
outputs = Vector(utxo),
lockTime = UInt32.zero)
// creditingTx: BaseTransaction = BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))),UInt32Impl(0))
// this is the information we need from the crediting TX
// to properly "link" it in the transaction we are creating
val outPoint = TransactionOutPoint(creditingTx.txId, UInt32.zero)
// outPoint: TransactionOutPoint = TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0)
val input = TransactionInput(
outPoint,
EmptyScriptSignature,
sequenceNumber = UInt32.zero)
// input: TransactionInput = TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),EmptyScriptSignature,UInt32Impl(0))
// Add a new input to our builder
builder += input
// res1: RawTxBuilder = RawTxBuilder()
// We can now generate a RawTxBuilderResult ready to be finalized
val builderResult = builder.result()
// builderResult: RawTxBuilderResult = RawTxBuilderResult(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d))),UInt32Impl(0))
// this contains the information needed to analyze our input during finalization
val inputInfo = P2PKHInputInfo(outPoint, amount, privKey.publicKey)
// inputInfo: P2PKHInputInfo = P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66))
// this is how much we are going to pay as a fee to the network
// for this example, we are going to pay 1 satoshi per byte
val feeRate = SatoshisPerByte(1.satoshi)
// feeRate: SatoshisPerByte = 1 sats/byte
val changePrivKey = ECPrivateKey.freshPrivateKey
// changePrivKey: ECPrivateKey = Masked(ECPrivateKey)
val changeSPK = P2PKHScriptPubKey(pubKey = changePrivKey.publicKey)
// changeSPK: P2PKHScriptPubKey = pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb)
// We chose a finalizer that adds a change output to our tx based on a fee rate
val finalizer = StandardNonInteractiveFinalizer(
Vector(inputInfo),
feeRate,
changeSPK)
// finalizer: StandardNonInteractiveFinalizer = StandardNonInteractiveFinalizer(Vector(P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66))),1 sats/byte,pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb))
// We can now finalize the tx builder result from earlier with this finalizer
val unsignedTx: Transaction = finalizer.buildTx(builderResult)
// unsignedTx: Transaction = BaseTransaction(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)), TransactionOutput(4775 sats,pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb))),UInt32Impl(0))
// We now turn to signing the unsigned transaction
// this contains all the information we need to
// validly sign the UTXO above
val utxoInfo = ScriptSignatureParams(inputInfo = inputInfo,
prevTransaction = creditingTx,
signers = Vector(privKey),
hashType =
HashType.sigHashAll)
// utxoInfo: ScriptSignatureParams[P2PKHInputInfo] = ScriptSignatureParams(P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(1))
// all of the UTXO spending information, since we only have
// one input, this is just one element
val utxoInfos: Vector[ScriptSignatureParams[InputInfo]] = Vector(utxoInfo)
// utxoInfos: Vector[ScriptSignatureParams[InputInfo]] = Vector(ScriptSignatureParams(P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(1)))
// Yay! Now we use the RawTxSigner object to sign the tx.
// The 'sign' method is going produce a validly signed transaction
// This is going to iterate through each of the UTXOs and use
// the corresponding ScriptSignatureParams to produce a validly
// signed input. This UTXO has:
// 1: one input
// 2: outputs (destination and change outputs)
// 3: a fee rate of 1 satoshi/byte
val signedTx: Transaction =
RawTxSigner.sign(
utx = unsignedTx,
utxoInfos = utxoInfos,
expectedFeeRate = feeRate
)
// signedTx: Transaction = BaseTransaction(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),P2PKHScriptSignature(ECPublicKeyBytes(ByteVector(33 bytes, 0x02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)), ECDigitalSignature(30440220627fc2103f7be50d464c9d331e3279251ee906436c91afb8ba8cb8ac82f7306002203edfa71859c4d8d3d8f8105ff6df5b4cc7a2b4d6c73cf3a55877b4f7f9b97ebd01)),UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)), TransactionOutput(4775 sats,pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb))),UInt32Impl(0))
```
```scala
signedTx.inputs.length
// res2: Int = 1
signedTx.outputs.length
// res3: Int = 2
//remember, you can call .hex on any bitcoin-s data structure to get the hex representation!
signedTx.hex
// res4: String = 020000000158cd6454471cd7f98e2d96b1ee6f4401c964ddc0784e7b103e17ab325732c37d000000006a4730440220627fc2103f7be50d464c9d331e3279251ee906436c91afb8ba8cb8ac82f7306002203edfa71859c4d8d3d8f8105ff6df5b4cc7a2b4d6c73cf3a55877b4f7f9b97ebd012102115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66000000000288130000000000001976a91480d74f124249a58880a7998bc10f99eb80b0f98d88aca7120000000000001976a914521c5467aef9b4c106840ef901fcd0fa7487d7bb88ac00000000
```

View file

@ -0,0 +1,65 @@
---
id: version-1.9.2-sign
title: Sign API
original_id: sign
---
### The [`Sign` API](/api/org/bitcoins/crypto/Sign)
This is the API we define to sign things with. It takes in an arbitrary byte vector and returns a `Future[ECDigitalSignature]`. The reason we incorporate `Future`s here is for extensibility of this API. We would like to provide implementations of this API for hardware devices, which need to be asynchrnous since they may require user input.
From [Sign.scala](/api/org/bitcoins/crypto/Sign):
```scala
import scodec.bits._
import org.bitcoins.crypto._
import scala.concurrent._
import scala.concurrent.duration._
trait Sign {
def signFunction: ByteVector => Future[ECDigitalSignature]
def signFuture(bytes: ByteVector): Future[ECDigitalSignature] =
signFunction(bytes)
def sign(bytes: ByteVector): ECDigitalSignature = {
Await.result(signFuture(bytes), 30.seconds)
}
def publicKey: ECPublicKey
}
```
The `ByteVector` that is input to the `signFunction` should be the hash that is output from [`TransactionSignatureSerializer`](/api/org/bitcoins/core/crypto/TransactionSignatureSerializer)'s `hashForSignature` method. Our in-memory [`BaseECKey`](/api/org/bitcoins/crypto/BaseECKey) types implement the `Sign` API.
If you wanted to implement a new `Sign` api for a hardware wallet, you can easily pass it into the `TxBuilder`/`Signer` classes to allow for you to use those devices to sign with Bitcoin-S.
This API is currently used to sign ordinary transactions with our [`Signer`](/api/org/bitcoins/core/wallet/signer/Signer)s. The `Signer` subtypes (i.e. `P2PKHSigner`) implement the specific functionality needed to produce a valid digital signature for their corresponding script type.
### The [`ExtSign`](/api/org/bitcoins/crypto/Sign) API.
An [ExtKey](/api/org/bitcoins/core/crypto/ExtKey) is a data structure that can be used to generate more keys from a parent key. For more information look at [hd-keys.md](../core/hd-keys.md)
You can sign with `ExtPrivateKey` the same way you could with a normal `ECPrivateKey`.
```scala
import org.bitcoins.core.hd._
import org.bitcoins.core.crypto._
val extPrivKey = ExtPrivateKey(ExtKeyVersion.SegWitMainNetPriv)
// extPrivKey: ExtPrivateKey = Masked(ExtPrivateKeyImpl)
extPrivKey.sign(DoubleSha256Digest.empty.bytes)
// res0: ECDigitalSignature = ECDigitalSignature(3045022100ad428f1b54cfb39e85f68fe1f22f859ed956da162d4279b70b96a1a5b24ec182022000cd632d703dadea9186621550a923df1edf808352f22dab0f41f031c694e0c1)
val path = BIP32Path(Vector(BIP32Node(0,false)))
// path: BIP32Path = m/0
extPrivKey.sign(DoubleSha256Digest.empty.bytes,path)
// res1: ECDigitalSignature = ECDigitalSignature(3044022054b0e675629d0ceb6e5aac6171244f516918bf5967aa741deab9bb745bed750e0220333bfbb14108ce3a87a17bd52ec6dae22a24a6bc4fb9efb3d75c112297babfc0)
```
With `ExtSign`, you can use `ExtPrivateKey` to sign transactions inside of `TxBuilder` since `UTXOSpendingInfo` takes in `Sign` as a parameter.
You can also provide a `path` to use to derive a child `ExtPrivateKey`, and then sign with that child private key

View file

@ -0,0 +1,127 @@
---
id: version-1.9.2-getting-started
title: Intro and Getting Started
original_id: getting-started
---
## Philosophy
Bitcoin-S is a loosely coupled set of cryptocurrency libraries for the JVM. They work well together, but also can be used
independently. This project's goal is NOT to be a full node implementation, rather a set of scalable cryptocurrency libraries
that use industry standard tools (rather than esoteric tech often found in cryptocurrency) where possible to make the lives of professional
software engineers, security engineers, devops engineers and accountants easier.
We are rapidly iterating on development with the goal of getting to a set of stable APIs that only change when the underlying bitcoin protocol changes.
If you are a professional working a cryptocurrency business and
have feedback on how to make your lives easier, please reach out on [slack](https://join.slack.com/t/suredbits/shared_invite/zt-eavycu0x-WQL7XOakzQo8tAy7jHHZUw),
[gitter](https://gitter.im/bitcoin-s-core/) or [twitter](https://twitter.com/Chris_Stewart_5/)!
## Getting prebuilt artifacts
### Java binaries
<details>
#### Latest release
Please see the release page on github, you can find it [here](https://github.com/bitcoin-s/bitcoin-s/releases)
#### Master builds
We build installers for mac, linux and windows everytime a PR is merged to master.
You can find the latest builds at this link:
https://github.com/bitcoin-s/bitcoin-s/actions/workflows/release.yml
Here is what the installers look like
![installers](/img/doc-imgs/github-artifacts.png)
</details>
### Docker
<details>
We publish docker images to docker hub on every PR merge and tag on github.
You can obtain the images for both the app server and oracle server on these
docker hub repos
[bitcoin-s-server docker hub repo](https://hub.docker.com/r/bitcoinscala/bitcoin-s-server/tags?page=1&ordering=last_updated)
[bitcoin-s-oracle-server docker hub repo](https://hub.docker.com/r/bitcoinscala/bitcoin-s-oracle-server/tags?page=1&ordering=last_updated)
</details>
### Library jars
<details>
Add this to your `build.sbt`:
```scala
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-bitcoind-rpc" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-core" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-chain" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-oracle" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-eclair-rpc" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-fee-provider" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-key-manager" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-lnd-rpc" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-node" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-oracle-explorer-client" % "1.9.1"
libraryDependencies +="org.bitcoin-s" % "bitcoin-s-secp256k1jni" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit-core" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-wallet" % "1.9.1"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-zmq" % "1.9.1"
```
### Nightly builds
You can also run on the bleeding edge of Bitcoin-S, by
adding a snapshot build to your `build.sbt`. The most
recent snapshot published is `1.9.1-91-1ad54070-SNAPSHOT`.
To fetch snapshots, you will need to add the correct
resolver in your `build.sbt`:
```sbt
resolvers += Resolver.sonatypeRepo("snapshots")
```
The official maven repo for releases is
https://repo1.maven.org/maven2/org/bitcoin-s/
The repo for snapshots, which are published after everytime something is merged to master:
https://oss.sonatype.org/content/repositories/snapshots/org/bitcoin-s/
</details>
## Building JARs yourself
Please see [our setup docs](getting-setup.md)
## If you want to setup Bitcoin-S locally for development
Please see [our setup docs](getting-setup.md)

View file

@ -0,0 +1,124 @@
---
id: version-1.9.2-key-manager
title: Key Manager
original_id: key-manager
---
### Key Manager
The key manager module's goal is to encapsulate all private key interactions with the [wallet](../wallet/wallet.md) project.
As of this writing, there is only one type of `KeyManager` - [`BIP39KeyManager`](/api/org/bitcoins/keymanager/bip39/BIP39KeyManager).
The [`BIP39KeyManager`](/api/org/bitcoins/keymanager/bip39/BIP39KeyManager) stores a [`MnemonicCode`](/api/org/bitcoins/core/crypto/MnemonicCode) on disk which can be decrypted and used as a hot wallet.
Over the long run, we want to make it so that the wallet project needs to communicate with the key-manager to access private keys.
This means that ALL SIGNING should be done inside of the key-manager, and private keys should not leave the key manager.
This makes it easier to reason about the security characteristics of our private keys, and a way to provide a uniform interface for alternative key storage systems (hsm, cloud based key storage, etc) to be plugged into the bitcoin-s library.
#### Creating a key manager
The first thing you need create a key manager is some entropy.
A popular way for bitcoin wallet's to represent entropy is [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) which you [can use in bitcoin-s](/api/org/bitcoins/core/crypto/BIP39Seed)
You can generate a `MnemonicCode` in bitcoin-s with the following code
```scala
import org.bitcoins.core.crypto._
//get 256 bits of random entropy
val entropy = MnemonicCode.getEntropy256Bits
// entropy: scodec.bits.BitVector = BitVector(256 bits, 0x3eb8d4d6450a76d79e3a007adc3d3493d9efd684b0ede33262bf28118a13ac4d)
val mnemonic = MnemonicCode.fromEntropy(entropy)
// mnemonic: MnemonicCode = Masked(MnemonicCodeImpl)
//you can print that mnemonic seed with this
println(mnemonic.words)
// Vector(dirt, shop, culture, meat, polar, hint, jump, divorce, kiss, tiger, essay, chicken, page, twice, barrel, buffalo, tobacco, narrow, quit, expand, board, antenna, raise, real)
```
Now that we have a `MnemonicCode` that was securely generated, we need to now create `KeyManagerParams` which tells us how to generate
generate specific kinds of addresses for wallets.
`KeyManagerParams` takes 3 parameters:
1. `seedPath` there is where we store the `MnemonicCode` on your file system
2. [`purpose`](/api/org/bitcoins/core/hd/HDPurpose) which represents what type of utxo this `KeyManager` is associated with. The specification for this is in [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)
3. [`network`](/api/org/bitcoins/core/config/NetworkParameters) what cryptocurrency network this key manager is associated with
This controls how the root key is defined. The combination of `purpose` and `network` determine how the root `ExtKey` is serialized. For more information on how this works please see [hd-keys](../core/hd-keys.md)
Now we can construct a native segwit key manager for the regtest network!
```scala
//this will create a temp directory with the prefix 'key-manager-example` that will
//have a file in it called "encrypted-bitcoin-s-seed.json"
val seedPath = Files.createTempDirectory("key-manager-example").resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
// seedPath: Path = /tmp/key-manager-example4040417810562189104/encrypted-bitcoin-s-seed.json
//let's create a native segwit key manager
val purpose = HDPurposes.SegWit
// purpose: HDPurpose = m/84'
//let's choose regtest as our network
val network = RegTest
// network: RegTest.type = RegTest
val kmParams = KeyManagerParams(seedPath, purpose, network)
// kmParams: KeyManagerParams = KeyManagerParams(/tmp/key-manager-example4040417810562189104/encrypted-bitcoin-s-seed.json,m/84',RegTest)
val aesPasswordOpt = Some(AesPassword.fromString("password"))
// aesPasswordOpt: Some[AesPassword] = Some(Masked(AesPassword))
val km = BIP39KeyManager.initializeWithMnemonic(aesPasswordOpt, mnemonic, None, kmParams)
// km: Either[KeyManagerInitializeError, BIP39KeyManager] = Right(org.bitcoins.keymanager.bip39.BIP39KeyManager@a5ad538)
val rootXPub = km.right.get.getRootXPub
// rootXPub: ExtPublicKey = vpub5SLqN2bLY4WeZyQCMFwoLmEJ59EBAukb7Cg7Lg7KmHstK6qxfxzisLahz9KRzSyyChsSeEpUbAXT6pgPq7CLGcGWa8bYZZFPFsWkwxTCZtj
println(rootXPub)
// vpub5SLqN2bLY4WeZyQCMFwoLmEJ59EBAukb7Cg7Lg7KmHstK6qxfxzisLahz9KRzSyyChsSeEpUbAXT6pgPq7CLGcGWa8bYZZFPFsWkwxTCZtj
```
Which should print something that looks like this
`vpub5SLqN2bLY4WeXxMqwJHJFBEwxSscGB2uDUnsTS3edVjZEwTrQDFDNqoR2xLqARQPabGaXsHSTenTRcqm2EnB9MpuC4vSk3LqSgNmGGZtuq7`
which is a native segwit `ExtPubKey` for the regtest network!
You can always change the `network` or `purpose` to support different things. You do _not_ need to initialize the key manager
again after initializing it once. You can use the same `mnemonic` for different networks, which you control `KeyManagerParams`.
```scala
//let's create a nested segwit key manager for mainnet
val mainnetKmParams = KeyManagerParams(seedPath, HDPurposes.SegWit, MainNet)
// mainnetKmParams: KeyManagerParams = KeyManagerParams(/tmp/key-manager-example4040417810562189104/encrypted-bitcoin-s-seed.json,m/84',MainNet)
//we do not need to all `initializeWithMnemonic()` again as we have saved the seed to dis
val mainnetKeyManager = BIP39KeyManager.fromMnemonic(mnemonic, mainnetKmParams, None, Instant.now)
// mainnetKeyManager: BIP39KeyManager = org.bitcoins.keymanager.bip39.BIP39KeyManager@60126619
val mainnetXpub = mainnetKeyManager.getRootXPub
// mainnetXpub: ExtPublicKey = zpub6jftahH18ngZyAAfgh6JB7cJm1oxwPiamekzUFgsHKPQXW6sgbeyMbDG4y9mz5beqGLfe9CiRowedy8ehtrPTYzv3VPEuCXLLmmLWKzoMeY
println(mainnetXpub)
// zpub6jftahH18ngZyAAfgh6JB7cJm1oxwPiamekzUFgsHKPQXW6sgbeyMbDG4y9mz5beqGLfe9CiRowedy8ehtrPTYzv3VPEuCXLLmmLWKzoMeY
```
Which gives us something that looks like this
`zpub6jftahH18ngZw98KGjRo5XcxeKTQ2eztsvskb1dC9XF5TLimQquTs6Ry7nBBA425D9joXmfgJJCexmJ1u2SELJZJfRi95gcnXadLpZzYb5c`
which is a p2sh wrapped segwit `ExtPubKey` for the bitcoin main network!
#### Creating a key manager from existing mnemonic
To create a `KeyManager` from existing mnemonic you need to specify the `seedPath` and then construct the `KeyManagerParams` that you would like.
Finally you call `KeyManager.fromParams()` that reads the mnemonic from disk and create's the key manager

View file

@ -0,0 +1,83 @@
---
id: version-1.9.2-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.getNeutrinoTestConfig().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))
```

View file

@ -0,0 +1,212 @@
---
id: version-1.9.2-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).
Note: It is safe to back up the `oracle.sqlite` file to a public place. The seed file contains
the cryptographic seed information. You need both the database and the seed file to restore the oracle.
Make sure you don't back the seed file to a place that is not safe.
## 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
- `setoraclename` `oraclename` Sets the oracle name in the database
- `getoraclename` gets the oraclename for the database
### 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}
```
### Set oracle name example
```
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "setoraclename", "params" : ["MY_ORACLE_NAME"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
{"result":"issue-34","error":null}
```
You can retrieve the oracle name with
```
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getoraclename", "params" : []}' -H "Content-Type: application/json" http://127.0.0.1:9998/
{"result":"MY_ORACLE_NAME","error":null}
```

View file

@ -0,0 +1,92 @@
---
id: version-1.9.2-secp256k1
title: Secp256k1
original_id: secp256k1
---
[Libsecp256k1](https://github.com/bitcoin-core/secp256k1) is used to preform cryptographic operations on the secp256k1 curve.
This is the curve that bitcoin uses. There is a _signficant_ speedup when using this library compared to java crypto libraries
like bouncy castle.
In bitcoin-s, we support native binaries for libsecp256k1
1. [linux 32 bit](../../secp256k1jni/natives/linux_32)
2. [linux 64 bit](../../secp256k1jni/natives/linux_64)
3. [mac osx 64 bit](../../secp256k1jni/natives/osx_64)
4. [windows 64 bit](../../secp256k1jni/natives/windows_64)
Bitcoin-s uses a zero dependency library called [`native-lib-loader`](https://github.com/scijava/native-lib-loader).
That does the appropriate loading of the library onto your classpath to be accessed.
### Using libsecp256k1
To tell if you have access to libsecp256k1 you can do the following
```scala
val isEnabled = org.bitcoin.Secp256k1Context.isEnabled()
println(s"Secp256k1Context.isEnabled=${isEnabled}")
```
If libsecp256k1 is enabled, you can use [NativeSecp256k1](/api/org/bitcoin/NativeSecp256k1)
with static method defined in the class.
```scala
val privKey = ECPrivateKey.freshPrivateKey
val pubKey = privKey.publicKey
val dataToSign = DoubleSha256Digest.empty
val signature = NativeSecp256k1.sign(dataToSign.bytes.toArray, privKey.bytes.toArray)
val verify = NativeSecp256k1.verify(dataToSign.bytes.toArray, signature, pubKey.bytes.toArray)
println(s"Verified with NativeSecp256k1 signature=${verify}")
//you can also just directly sign with the ECKey interface:
val signature2 = privKey.sign(dataToSign)
val verified2 = pubKey.verify(dataToSign, signature2)
println(s"Verified with NativeSecp256k1 again=${verified2}")
```
### When libsecp256k1 isn't available, or you want to turn it off
There are two reasons you wouldn't want to use libsecp256k1
1. You don't trust the pre-compiled binaries we are using
2. Your OS/arch is not supported
There are two ways you can circumvent libsecp256k1
1. Set `DISABLE_SECP256K1=true` in your environment variables. This will force `CryptoContext.default` to return false which will make Bitcoin-S act like `Secp256k1Context.isEnabled()` has returned false.
2. Call Bouncy castle methods in `ECKey`.
Here is an example of calling bouncy castle methods in `ECKey`
```scala
val privKey = ECPrivateKey.freshPrivateKey
// privKey: ECPrivateKey = Masked(ECPrivateKey)
// calls bouncy castle indirectly via CryptoContext
val publicKey = privKey.publicKey
// publicKey: ECPublicKey = ECPublicKey(03a9e51ff5e03f25f0240cab576cef27cf4b793de086b711b4c2388c5dc1451763)
val dataToSign = DoubleSha256Digest.empty
// dataToSign: DoubleSha256Digest = DoubleSha256Digest(0000000000000000000000000000000000000000000000000000000000000000)
// calls bouncy castle indirectly via CryptoContext
val signature = privKey.sign(dataToSign.bytes)
// signature: ECDigitalSignature = ECDigitalSignature(304402203227ec8c9e5a6fac2acd70c8c6f08d9f90941821d25cc046007f448e78caecc80220781ad462e7c862df211bee1dd81b597327fa35f78a26c4501ebfd7f81bec7e7a)
// calls bouncy castle indirectly via CryptoContext
val verified = publicKey.verify(dataToSign.bytes, signature)
// verified: Boolean = true
println(s"Verified with bouncy castle=${verified}")
// Verified with bouncy castle=true
```
### Building libsecp256k1
[See instructions here](add-to-jni.md#adding-to-bitcoin-s)

View file

@ -0,0 +1,235 @@
---
id: version-1.9.2-security
title: Security
original_id: security
---
The Bitcoin-S developers take security very seriously. This library has
very few dependencies (at least in the `core` module), which is for
security reasons.
## Disclosure
If you have any security disclosures related to Bitcoin-S, please send an
email to either [stewart.chris1234@gmail.com](mailto:stewart.chris1234@gmail.com?subject=Bitcoin-S%20Security%20Disclosure),
[nadavk25@gmail.com](mailto:nadavk25@gmail.com?subject=Bitcoin-S%20Security%20Disclosure),
or [benthecarman@live.com](mailto:benthecarman@live.com?subject=Bitcoin-S%20Security%20Disclosure).
If you want to encrypt said email (which you should), Ben's key is available on [his Keybase](https://keybase.io/benthecarman/pgp_keys.asc?fingerprint=0ad83877c1f0cd1ee9bd660ad7cc770b81fd22a8), and Chris and Nadav's
are posted below:
Chris:
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=9yPz
-----END PGP PUBLIC KEY BLOCK-----
```
Nadav:
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
yCLXAg==
=fx/l
-----END PGP PUBLIC KEY BLOCK-----
```

View file

@ -0,0 +1,96 @@
---
id: version-1.9.2-ui-setup
title: Installing the DLC Wallet UI
original_id: ui-setup
---
# Easy setup
We have desktop installers for mac, windows and linux. This requires you to be signed into a github account to download.
The link to the installers is [suredbits.com/bitcoin-s](https://suredbits.com/bitcoin-s)
You can download the appropriate installer for your machine
![Example banner](/img/installers.png)
The downside of this setup is it uses an old UI that we are working to get rid of.
This UI is missing new features that drastically improve UX.
Once you download and install the wallet, deposit 100,000 sats and [find an event you want to bet on](https://oracle.suredbits.com/)!
The wallet will take roughly 20-30 minutes to synchronize with the bitcoin network. If you deposit funds before
the synchronization finishes, the funds may not show up right away. This is expected. They will show up when the sync is done.
For more information about building a DLC with this UI, checkout this youtube tutorial I recorded:
https://youtu.be/oR0I0aHxNMM?t=219
# Advanced setup
This requires command line skills.
### Starting the backend
From the image above, download the `bitcoin-s-server` artifact.
![Example banner](/img/installers.png)
After unzipping, you will need to run `chmod +x ./bin/bitcoin-s-server` from the terminal make the file executable.
After making the file executable, you can start the server with
```
unzip bitcoin-s-server.zip
cd bitcoin-s-server
chmod +x ./bin/bitcoin-s-server
./bin/bitcoin-s-server
```
This starts the backend and will begin synchronizing with the bitcoin network.
### Building and starting the frontend
Here are the instructions to build, you can paste this into your terminal
```
git clone https://github.com/bitcoin-s/bitcoin-s-ts.git
cd bitcoin-s-ts
cd wallet-server-ui && npm i && npm run build
cd ../wallet-server-ui-proxy && npm i && npm run startlocal
```
The last command, `npm run startlocal` should result in server starting with logs that look like this
```
> wallet-server-ui-proxy@1.9.0 startlocal
> DEFAULT_UI_PASSWORD=none BITCOIN_S_SERVER_RPC_PASSWORD=password npx ts-node server.ts
...
ConfigureServerURL() http://localhost:9999/
ConfigureAuthorizationHeader() Basic Yml0Y29pbnM6cGFzc3dvcmQ=
[HPM] Proxy created: / -> http://localhost:9999/
[HPM] Proxy rewrite rule created: "^/api/v0" ~> ""
[HPM] Proxy created: / -> ws://localhost:19999/events
[HPM] Proxy rewrite rule created: "^/websocket" ~> ""
2022-03-11T17:05:19.238Z info: starting HTTP server
2022-03-11T17:05:19.242Z info: Web Server started on port: 3002 ⚡
```
Now if you navigate to your web browser, you should see a page like this at `http://localhost:3002`
![Alt text](/img/Screenshot%20from%202022-03-11%2011-20-17.png)
The password is `none`, enter that and you should see the wallet!
![Alt text](/img/Screenshot%20from%202022-03-11%2011-21-47.png)
Deposit 100,000 sats and [find an event you want to bet on](https://oracle.suredbits.com/)!
The wallet will take roughly 20-30 minutes to synchronize with the bitcoin network. If you deposit funds before
the synchronization finishes, the funds may not show up right away. This is expected. They will show up when the sync is done.
After the synchronization is done, you should be good to do a DLC! :tada:

View file

@ -0,0 +1,319 @@
---
id: version-1.9.2-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
},
"hex": "fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60"
},
"oracleInfo": {
"announcement": {
"announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5",
"publicKey": "d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a",
"event": {
"nonces": [
"ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14"
],
"maturity": "2021-02-02T00:00:00Z",
"descriptor": {
"outcomes": [
"Republican_win",
"Democrat_win",
"other"
],
"hex": "fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f74686572"
},
"eventId": "2020-us-election"
},
"hex": "fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e"
}
}
}
```
### 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. 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 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 \
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,
"offerCollateral": 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:

View file

@ -0,0 +1,409 @@
---
id: version-1.9.2-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}]"
fdd82efd031f00000000000186a0fda7204e0011fda72642000400000000fda728020000fd9c40000000fda728020000fda604fdc3500000fda728020000fdafc8fe000186a00000fda728020000fe0001fffffe000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65
```
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 fdd82efd031f00000000000186a0fda7204e0011fda72642000400000000fda728020000fd9c40000000fda728020000fda604fdc3500000fda728020000fdafc8fe000186a00000fda728020000fe0001fffffe000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65
{
"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": [
]
},
"hex": "fda7204e0011fda72642000400000000fda728020000fd9c40000000fda728020000fda604fdc3500000fda728020000fdafc8fe000186a00000fda728020000fe0001fffffe000186a00000fda724020000"
},
"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,
"hex": "fdd80a11000200074254432f555344000000000011"
},
"eventId": "bitcoin-s-price-example"
},
"hex": "fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65"
}
}
}
```
### 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. refund locktime
As of this writing, the current block height is `705161` . For the sake of this example
I'm going to pick a refund locktime 2 weeks in advance `refundLocktime=707177`
Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral.
```
./bitcoin-s-cli createdlcoffer fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \
50000 \
1 \
> 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,
"offerCollateral": 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`.

View file

@ -1,4 +1,5 @@
[
"1.9.2",
"1.9.1",
"1.9.0",
"1.8.0",