Add version 1.9.1 to the website (#4269)

This commit is contained in:
Chris Stewart 2022-04-18 13:23:52 -05:00 committed by GitHub
parent 47b65cae65
commit 8cda343fd3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 3906 additions and 1 deletions

View file

@ -23,7 +23,7 @@ import scala.util.Properties
object CommonSettings { object CommonSettings {
val previousStableVersion: String = "1.9.0" val previousStableVersion: String = "1.9.1"
private def isCI = { private def isCI = {
Properties Properties

View file

@ -17,6 +17,9 @@
"applications/server": { "applications/server": {
"title": "Application Server" "title": "Application Server"
}, },
"applications/web-ui": {
"title": "Application server and Web UI"
},
"bips": { "bips": {
"title": "Supported BIPs" "title": "Supported BIPs"
}, },
@ -958,6 +961,66 @@
}, },
"version-1.9.0/wallet/version-1.9.0-wallet": { "version-1.9.0/wallet/version-1.9.0-wallet": {
"title": "Wallet" "title": "Wallet"
},
"version-1.9.1/applications/version-1.9.1-cli": {
"title": "CLI"
},
"version-1.9.1/applications/version-1.9.1-server": {
"title": "Application Server"
},
"version-1.9.1/applications/version-1.9.1-web-ui": {
"title": "Application server and Web UI"
},
"version-1.9.1/config/version-1.9.1-configuration": {
"title": "Application Configuration"
},
"version-1.9.1/core/version-1.9.1-addresses": {
"title": "Generating Addresses"
},
"version-1.9.1/core/version-1.9.1-dlc": {
"title": "Discreet Log Contract Data Structures"
},
"version-1.9.1/core/version-1.9.1-hd-keys": {
"title": "HD Key Generation"
},
"version-1.9.1/core/version-1.9.1-txbuilder": {
"title": "TxBuilder Example"
},
"version-1.9.1/crypto/version-1.9.1-sign": {
"title": "Sign API"
},
"version-1.9.1/version-1.9.1-getting-setup": {
"title": "Getting Bitcoin-S installed on your machine"
},
"version-1.9.1/version-1.9.1-getting-started": {
"title": "Intro and Getting Started"
},
"version-1.9.1/key-manager/version-1.9.1-key-manager": {
"title": "Key Manager"
},
"version-1.9.1/node/version-1.9.1-node": {
"title": "Light Client"
},
"version-1.9.1/oracle/version-1.9.1-oracle-server": {
"title": "Oracle Server"
},
"version-1.9.1/secp256k1/version-1.9.1-secp256k1": {
"title": "Secp256k1"
},
"version-1.9.1/version-1.9.1-ui-setup": {
"title": "Installing the DLC Wallet UI"
},
"version-1.9.1/wallet/version-1.9.1-dlc": {
"title": "Executing A DLC with Bitcoin-S"
},
"version-1.9.1/wallet/version-1.9.1-wallet-election-example": {
"title": "Wallet Election Example"
},
"version-1.9.1/wallet/version-1.9.1-wallet-price-example": {
"title": "Wallet Price Example"
},
"version-1.9.1/wallet/version-1.9.1-wallet-rpc": {
"title": "Wallet RPC Examples"
} }
}, },
"links": { "links": {

View file

@ -0,0 +1,62 @@
---
id: version-1.9.1-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).
### 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,386 @@
---
id: version-1.9.1-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 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
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]` `locktime` `refundlocktime` - Creates a DLC offer that another party can accept
- `contractInfo` - Hex encoded contractInfo message
- `collateral` - Satoshis to fund your side of the DLC
- `feerate` - Fee rate for both funding and closing transactions, in sats/vbytes
- `locktime` - Locktime of the contract execution transactions
- `refundlocktime` - Locktime of the refund transaction
- `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
- `acceptdlcofferfromfile` `path` `[destination]` - Accepts a DLC offer given from another party
- `path` - Path to dlc offer file
- `destination` - Path to write dlc accept message
- `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
- `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,22 @@
---
id: version-1.9.1-web-ui
title: Application server and Web UI
original_id: web-ui
---
## Application server and Web UI
### docker-compose
To start the application server along with the Web UI you can use `docker-compose`.
We provide a `docker-compose.yml` (https://github.com/bitcoin-s/bitcoin-s/blob/master/docker-compose.yml) file that uses the latest stable versions of the application server and the Web UI.
The application server requires a password to be set in order to start. You can use the `APP_PASSWORD` environment variable to do so.
```shell
$ APP_PASSWORD=<your password> docker-compose up
```
The server is configured to work as a neutrino wallet, and it uses `neutrino.suredbits.com` as a peer.
If you want to connect to another peer change the `BITCOIN_S_NODE_PEERS` variable in the `docker-conpose.yml` file.

View file

@ -0,0 +1,505 @@
---
title: Application Configuration
id: version-1.9.1-configuration
original_id: configuration
---
Bitcoin-S uses [HOCON](https://github.com/lightbend/config/blob/master/HOCON.md)
to configure various parts of the application the library offers. HOCON is a superset of JSON, that is, all valid JSON
is valid HOCON.
All configuration for Bitcoin-S is under the `bitcoin-s` key.
If you have a file `application.conf` anywhere on your classpath when using bitcoin-s, the values there take precedence
over the ones found in our
`reference.conf`. We also look for the file `bitcoin-s.conf` in the current Bitcoin-S data directory.
The resolved configuration gets parsed by
[`AppConfig`](/api/org/bitcoins/db/AppConfig).
`AppConfig` is an abstract class that's implemented by corresponding case classes in the `wallet`, `chain` and `node`
projects. Here's some examples of how to construct a wallet configuration:
```scala
import org.bitcoins.wallet.config.WalletAppConfig
import com.typesafe.config.ConfigFactory
import java.nio.file.Paths
import scala.util.Properties
import scala.concurrent.ExecutionContext.Implicits.global
// reads $HOME/.bitcoin-s/
val defaultConfig = WalletAppConfig.fromDefaultDatadir()
// reads a custom data directory
val customDirectory = Paths.get(Properties.userHome, "custom-bitcoin-s-directory")
val configFromCustomDatadir = WalletAppConfig(customDirectory, Vector.empty)
// reads a custom data directory and overrides the network to be testnet3
val customOverride = ConfigFactory.parseString("bitcoin-s.network = testnet3")
val configFromCustomDirAndOverride = WalletAppConfig(customDirectory, Vector(customOverride))
```
You can pass as many `com.typesafe.config.Config`s as you'd like. If any keys appear multiple times the last one
encountered takes precedence.
## Command Line Options
There are a few command line options available that take precedence over configuration file.
- `--datadir <directory>`
`datadir` sets the data directory instead of using the default `$HOME/.bitcoin-s`
- `--rpcbind <ip>`
`rpcbind` sets the interface the rpc server binds to instead of using the default `127.0.0.1`
- `--rpcport <port>`
`rpcport` sets the port the rpc server binds to instead of using the default `9999`
- `--force-recalc-chainwork`
`force-recalc-chainwork` will force a recalculation of the entire chain's chain work, this can be useful if there is
an incompatible migration or if it got out of sync.
- `-Dlogback.configurationFile=/path/to/config.xml`
You can set a custom logback configuration. If you need help creating a custom logback file you can
read [the logback configuration documentation](http://logback.qos.ch/manual/configuration.html).
## Internal configuration
Database connections are also configured by using HOCON. This is done
in [`reference.conf`](https://github.com/bitcoin-s/bitcoin-s/blob/master/db-commons/src/main/resources/reference.conf)
inside the `db-commons` module. The options exposed here are **not** intended to be used by users of Bitcoin-S, and are
internal only.
## Database Migrations
All of our modules that require databases now have database migrations. The tool we use for these migrations is
called [flyway](https://flywaydb.org/). To find your projects migraitons, you need to look inside of the
`[project-name]/src/main/resources/[database-name]/migration/`. For example, the chain projects migrations live under
the path `chain/src/main/resources/chaindb/migration/V1__chain_db_baseline.sql`.
Migrations can be executed by calling
the [`DbManagement.migrate()`](https://github.com/bitcoin-s/bitcoin-s/blob/e387d075b0ff2e0a0fec15788fcb48e4ddc4d9d5/db-commons/src/main/scala/org/bitcoins/db/DbManagement.scala#L92)
method. Migrations are applied by default on server startup, via
the [`AppConfig.start()`](https://github.com/bitcoin-s/bitcoin-s/blob/master/db-commons/src/main/scala/org/bitcoins/db/AppConfig.scala#L49)
method.
These migrations are setup so that project's databases and migrations are independent of each other. Therefore if you
want to use the `bitcoin-s-chain` project, but not the `bitcoin-s-wallet` project, wallet migrations are not applied. It
should be noted if you are using a module as a library, you are responsible for configuring the database via
[slick's configuration](https://scala-slick.org/doc/3.3.1/database.html#using-typesafe-config) and calling
[`AppConfig.start()`](https://github.com/bitcoin-s/bitcoin-s/blob/master/db-commons/src/main/scala/org/bitcoins/db/AppConfig.scala#L49)
to ensure the entire module is initialized correctly.
## Example Configuration File
```$xslt
bitcoin-s {
# the network your bitcoin-s node is running on
network = "testnet3" # regtest, testnet3, mainnet, signet
# specify what backend you are using with bitcoin-s
# by default we do neutrino, but you can also connect
# bitcoind with the configuration settings in bitcoin-s.bitcoind-rpc
node.mode = neutrino # neutrino, bitcoind
# configurations for connecting to bitcoind
bitcoind-rpc {
# bitcoind rpc username
rpcuser = user
# bitcoind rpc password
# If your password contains the characters '$','{', '}', '[', ']', ':', '=', ',', '+', '#', '`', '^', '?', '!', '@', '*', '&', whitespace
# or the string "//", enclose it in double quotes
# rpcpassword = "password=" if the original password is password=, rpcpassword = "passwo//rd" if the original password is passwo//rd etc.
# If it contains '\' or '"', escape it with '\'
# rpcpassword = "pass\\word" if the original password is pass\word, rpcpassword = "pass\"word" if the original password is pass"word
rpcpassword = password
# Binary location of bitcoind
binary = ${HOME}/.bitcoin-s/binaries/bitcoind/bitcoin-0.20.1/bin/bitcoind
# bitcoind datadir
datadir = ${HOME}/.bitcoin
# bitcoind network host
connect = localhost
# bitcoind p2p port
port = 8333
# bitcoind rpc host
rpcconnect = localhost
# bitcoind rpc port
rpcport = 8332
# bitcoind zmq raw tx
zmqpubrawtx = "tcp://127.0.0.1:28332"
# bitcoind zmq raw block
zmqpubrawblock = "tcp://127.0.0.1:28333"
# bitcoind zmq hash tx
zmqpubhashtx = "tcp://127.0.0.1:28330"
# bitcoind zmq raw block
zmqpubhashblock = "tcp://127.0.0.1:28331"
#If you have a bitcoind instance that is running remotely on another machine, you should set it to true
isRemote = false
}
# settings if you are using a neutrino node in bitcoin-s
node {
# a list of peer addresses in form "hostname:portnumber"
# Port number is optional, the default value is 8333 for mainnet,
# 18333 for testnet and 18444 for regtest.
# by default we provide a testnet peer to connect to
peers = ["neutrino.testnet3.suredbits.com:18333"]
hikari-logging = true
hikari-logging-interval = 10 minute
# whether to have p2p peers relay us unconfirmed txs
relay = false
}
proxy {
# You can configure SOCKS5 proxy to use Tor for outgoing connections
enabled = false
socks5 = "127.0.0.1:9050"
}
# tor settings
tor {
# You can enable Tor for incoming connections
enabled = false
control = "127.0.0.1:9051"
# Tor daemon can be provided by the node operator.
# If this parameter set to true, bitcoin-s will connect the provided Tor daemon.
# Otherwise bitcoin-s will start its own pre-packaged daemon.
provided = false
# This parameter allows to use random port numbers for pre-packaged Tor daemon,
# which is useful if another Tor daemon instance already bound SOCKS5 and control ports.
# In this case bitcoin-s.tor.control and bitcoin-s.proxy.socks5
# addresses will be automatically changed to "localhost:<random port>"
use-random-ports = true
# The password used to arrive at the HashedControlPassword for the control port.
# If provided, the HASHEDPASSWORD authentication method will be used instead of
# the SAFECOOKIE one.
# password = securePassword
# The path to the private key of the onion service being created
# privateKeyPath = /path/to/priv/key
}
# settings for the chain module
chain {
force-recalc-chainwork = false
neutrino {
filter-header-batch-size.default = 2000
filter-header-batch-size.regtest = 10
# You can set a network specific filter-header-batch-size
# by adding a trailing `.networkId` (main, test, regtest)
# It is recommended to keep the main and test batch size high
# to keep the sync time fast, however, for regtest it should be small
# so it does not exceed the chain size.
filter-batch-size = 1000
}
hikari-logging = true
hikari-logging-interval = 10 minute
}
# settings for wallet module
wallet {
# You can have multiple wallets by setting a different
# wallet name for each of them. They will each have
# their own unique seed and database or schema,
# depending on the database driver.
# The wallet name can contain letters, numbers, and underscores '_'.
# walletName = MyWallet0
defaultAccountType = segwit # legacy, segwit, nested-segwit
bloomFalsePositiveRate = 0.0001 # percentage
# the number of consecutive addresses that we do not
# discover funds in before we mark as rescan as exhausted
# this is needed because we can never truely tell how many addresses
# the wallet has used when executing a rescan from a seed
addressGapLimit = 100
# the number of addresses that get generated everytime
# we need to rescan. If a match occurs within the addressGapLimit
# we generate another discoveryBatchSize addresses and then rescan again
discoveryBatchSize = 100
requiredConfirmations = 6
# Expected average fee rate over the long term
# in satoshis per virtual byte
longTermFeeRate = 10
# How big the address queue size is before we throw an exception
# because of an overflow
addressQueueSize = 10
# How long we attempt to generate an address for
# before we timeout
addressQueueTimeout = 5 seconds
# Allow external payout and change addresses in DLCs
# By default all DLC addresses are generated by the wallet itself
allowExternalDLCAddresses = false
# How often the wallet will rebroadcast unconfirmed transactions
rebroadcastFrequency = 4 hours
hikari-logging = true
hikari-logging-interval = 10 minute
}
keymanager {
# You can optionally set a BIP 39 password
# bip39password = "changeMe"
# Password that your seed is encrypted with
# aesPassword = changeMe
# At least 16 bytes of entropy encoded in hex
# This will be used as the seed for any
# project that is dependent on the keymanager
# entropy = ""
}
# Bitcoin-S provides manny different fee providers
# You can configure your server to use any of them
# Below is some examples of different options
fee-provider {
# name = mempoolspace # Uses mempool.space's api
# The target is optional for mempool.space
# It refers to the expected number of blocks until confirmation
# target = 6
# name = bitcoinerlive # Uses bitcoiner.live's api
# The target is optional for Bitcoiner Live
# It refers to the expected number of blocks until confirmation
# target = 6
# name = bitgo # Uses BitGo's api
# The target is optional for BitGo
# It refers to the expected number of blocks until confirmation
# target = 6
# name = constant # A constant fee rate in sats/vbyte
# target = 1 # Will always use 1 sat/vbyte
}
dlcnode {
# The address we are listening on for incoming connections for DLCs
# Binding to 0.0.0.0 makes us listen to all incoming connections
# Consider using 127.0.0.1 listen address if Tor is enabled.
# listen = "0.0.0.0:2862"
# The address our peers use to connect to our node.
# By default it's the same as the listen address,
# or if Tor is enabled, the hidden service's onion address.
# You can specify a port number like this "192.168.0.1:12345",
# The default port number is the same as in the listen adrress
# external-ip = "192.168.0.1"
}
server {
# The port we bind our rpc server on
rpcport = 9999
# The ip address we bind our server too
rpcbind = "127.0.0.1"
# The port we bind our websocket server on
wsport = 19999
# The ip address we bind the websocket server too
wsbind = "127.0.0.1"
# The basic auth password. It must me must be non empty.
password = topsecret
}
oracle {
# The port we bind our rpc server on
rpcport = 9998
# The ip address we bind our server too
rpcbind = "127.0.0.1"
# The basic auth password. It must me must be non empty.
password = supersecret
hikari-logging = true
hikari-logging-interval = 10 minute
db {
path = ${bitcoin-s.datadir}/oracle/
}
}
dbDefault = {
dataSourceClass = slick.jdbc.DatabaseUrlDataSource
profile = "slick.jdbc.SQLiteProfile$"
db {
# for information on parameters available here see
# https://scala-slick.org/doc/3.3.1/api/index.html#slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver,ClassLoader):Database
path = ${bitcoin-s.datadir}/${bitcoin-s.network}/
driver = org.sqlite.JDBC
user = ""
password = ""
host = localhost
port = 5432
# this needs to be set to 1 for SQLITE as it does not support concurrent database operations
# see: https://github.com/bitcoin-s/bitcoin-s/pull/1840
numThreads = 1
queueSize=5000
connectionPool = "HikariCP"
registerMbeans = true
}
hikari-logging = false
hikari-logging-interval = 10 minute
}
testkit {
pg {
#enabled postgres backend database for all test cases
enabled = false
}
}
}
akka {
loglevel = "OFF"
stdout-loglevel = "OFF"
http {
client {
# The time after which an idle connection will be automatically closed.
# Set to `infinite` to completely disable idle connection timeouts.
# some requests potentially take a long time, like generate and prune
idle-timeout = 5 minutes
}
server {
# The amount of time until a request times out on the server
# If you have a large payload this may need to be bumped
# https://doc.akka.io/docs/akka-http/current/common/timeouts.html#request-timeout
request-timeout = 10s
}
}
actor {
debug {
# enable DEBUG logging of all AutoReceiveMessages (Kill, PoisonPill etc.)
autoreceive= off
# enable function of LoggingReceive, which is to log any received message at
# DEBUG level
receive = on
# enable DEBUG logging of unhandled messages
unhandled = off
# enable DEBUG logging of actor lifecycle changes
lifecycle = off
event-stream=off
}
}
}
```
## Database configuration
By default, bitcoin-s uses Sqlite to store its data. It creates three Sqlite databases
in `~/.bitcoin-s/${network}`: `chain.sqlite` for `chain` project,
`node.sqlite` for `node` project and `wallet.sqlite` the wallet. This is the default configuration, it doesn't require
additional changes in the config file.
`bitcoin-s` also supports PostgreSQL as a database backend. In order to use a PostgreSQL database for all project you
need to add following into your config file:
```$xslt
bitcoin-s {
common {
profile = "slick.jdbc.PostgresProfile$"
db {
driver = org.postgresql.Driver
# these 3 options will result into a jdbc url of
# "jdbc:postgresql://localhost:5432/database"
name = database
host = localhost
port = 5432
user = "user"
password = "topsecret"
numThreads = 5
# http://scala-slick.org/doc/3.3.3/database.html
connectionPool = "HikariCP"
registerMbeans = true
}
}
chain.profile = ${bitcoin-s.common.profile}
chain.db = ${bitcoin-s.common.db}
chain.db.poolName = "chain-connection-pool"
node.profile = ${bitcoin-s.common.profile}
node.db = ${bitcoin-s.common.db}
node.db.poolName = "node-connection-pool"
wallet.profile = ${bitcoin-s.common.profile}
wallet.db = ${bitcoin-s.common.db}
wallet.db.poolName = "wallet-connection-pool"
oracle.profile = ${bitcoin-s.common.profile}
oracle.db = ${bitcoin-s.common.db}
oracle.db.poolName = "oracle-connection-pool"
}
```
The database driver will create a separate SQL namespace for each sub-project: `chain`, `node` and `wallet`.
Also you can use mix databases and drivers in one configuration. For example, This configuration file enables Sqlite
for `node` project (it's default, so its configuration is omitted), and `walletdb` and `chaindb` PostgreSQL databases
for `wallet` and `chain` projects:
```$xslt
bitcoin-s {
chain {
profile = "slick.jdbc.PostgresProfile$"
db {
driver = org.postgresql.Driver
name = chaindb
host = localhost
port = 5432
user = "user"
password = "topsecret"
}
}
wallet {
profile = "slick.jdbc.PostgresProfile$"
db {
driver = org.postgresql.Driver
name = walletdb
host = localhost
port = 5432
user = "user"
password = "topsecret"
}
}
}
```

View file

@ -0,0 +1,59 @@
---
id: version-1.9.1-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(02f07024f9e977133041d5a7768fcb582385ce5c09b2711f0202e473d23f52ee64)
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 = tb1q3gftc5dytyvj0rssxl8v2xragetulx7fs5gulj
println(segwitAddress.toString)
// tb1q3gftc5dytyvj0rssxl8v2xragetulx7fs5gulj
```
## 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 = mt71zJNhcSPkd8mBEgcC21nWYzzHo1JJRK
println(legacyAddress.toString)
// mt71zJNhcSPkd8mBEgcC21nWYzzHo1JJRK
```

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,145 @@
---
id: version-1.9.1-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, 0x4e12eada1665db940def2133017c3fa955277b83ca6ce433b553888be7eff325)
val mnemonicCode = MnemonicCode.fromEntropy(entropy)
// mnemonicCode: MnemonicCode = Masked(MnemonicCodeImpl)
mnemonicCode.words // the phrase the user should write down
// res0: Vector[String] = Vector(evoke, nuclear, repair, coast, frozen, skate, dash, tomorrow, credit, armor, avocado, famous, fame, saddle, august, eternal, tomorrow, oval, female, baby, salmon, wave, smart, penalty) // 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 = zpub6jftahH18ngZwtyTykBBqNvG8AxponMZu7tmYamRkZ8zEhDJyrZWdrC2erRM72V5ANzaavsJdmA4NBXFmVN2ZRAwqXmLwHF3qFjkmRr82F3
// 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 = zpub6r5CUWGcG2ni3QttE2kxXPjr8CAnESwaZhGE8yNuFC1r3EgeSPeMCpPFjkMAwKiwaMWURT9LooxXdmf7AZXPbBxRL57sMrMoeS85CY9RCnv
// 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 = tb1qal7kxnp4pa7u0csg0mc4m9trgz0x6y3r6kvgj2
// tada! We just generated an address you can send money to,
// without having access to the private key!
firstAccountAddress.value
// res2: String = tb1qal7kxnp4pa7u0csg0mc4m9trgz0x6y3r6kvgj2
// 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.1-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@9cb4f66[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(03361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f)
// 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(d7e88521d195628c8042c7065ec8ca503b52471f)
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(d7e88521d195628c8042c7065ec8ca503b52471f))
// 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(8d9fad5965ae03761617646301a5d9131ab82d1f)
// 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(8d9fad5965ae03761617646301a5d9131ab82d1f)))
// 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(d7e88521d195628c8042c7065ec8ca503b52471f))),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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0)
val input = TransactionInput(
outPoint,
EmptyScriptSignature,
sequenceNumber = UInt32.zero)
// input: TransactionInput = TransactionInputImpl(TransactionOutPoint(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f: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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(8d9fad5965ae03761617646301a5d9131ab82d1f))),UInt32Impl(0))
// this contains the information needed to analyze our input during finalization
val inputInfo = P2PKHInputInfo(outPoint, amount, privKey.publicKey)
// inputInfo: P2PKHInputInfo = P2PKHInputInfo(TransactionOutPoint(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),10000 sats,ECPublicKey(03361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f))
// 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(f62cb3759d33009469fb06fea8e06dc94be9ed9e)
// 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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),10000 sats,ECPublicKey(03361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f))),1 sats/byte,pkh(f62cb3759d33009469fb06fea8e06dc94be9ed9e))
// 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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(8d9fad5965ae03761617646301a5d9131ab82d1f)), TransactionOutput(4775 sats,pkh(f62cb3759d33009469fb06fea8e06dc94be9ed9e))),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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),10000 sats,ECPublicKey(03361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(d7e88521d195628c8042c7065ec8ca503b52471f))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(Int32Impl(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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),10000 sats,ECPublicKey(03361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(d7e88521d195628c8042c7065ec8ca503b52471f))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(Int32Impl(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(e1900403a26cca197b3d468db05c96e96abdd1bf9baab86487bc4ac8317efa8f:0),P2PKHScriptSignature(ECPublicKeyBytes(ByteVector(33 bytes, 0x03361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f)), ECDigitalSignature(304402207b696d8702691be8148666a3d9ccbb886406ddd0355be8eb357f3462f5383fbf02205e08a5808716cf1e134094b9cffdf48343b0c2a713209895915895b778422f6a01)),UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(8d9fad5965ae03761617646301a5d9131ab82d1f)), TransactionOutput(4775 sats,pkh(f62cb3759d33009469fb06fea8e06dc94be9ed9e))),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 = 02000000018ffa7e31c84abc8764b8aa9bbfd1bd6ae9965cb08d463d7b19ca6ca2030490e1000000006a47304402207b696d8702691be8148666a3d9ccbb886406ddd0355be8eb357f3462f5383fbf02205e08a5808716cf1e134094b9cffdf48343b0c2a713209895915895b778422f6a012103361c1d223e49038ab8f2610e50d70433d3aa8ee74faedc7fd6937b1aac9cc25f000000000288130000000000001976a9148d9fad5965ae03761617646301a5d9131ab82d1f88aca7120000000000001976a914f62cb3759d33009469fb06fea8e06dc94be9ed9e88ac00000000
```

View file

@ -0,0 +1,65 @@
---
id: version-1.9.1-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(30440220478dcf5f04b8923a6e5195eef976b6a98c6e9e6b5e18f899a69166b26a5e7e0202200e05fbf7c67693430ca4309846e133a8d285262799c244b08e49b18d795334bf)
val path = BIP32Path(Vector(BIP32Node(0,false)))
// path: BIP32Path = m/0
extPrivKey.sign(DoubleSha256Digest.empty.bytes,path)
// res1: ECDigitalSignature = ECDigitalSignature(3044022057deb86912f4a949328b2bf17625fb6992006b5bbfcce10af26d7b3bd09c4c1f0220174abe2daf9e06e5b69c8e8b943e6471ace8fcfde801b2a16e5f05bb19f91329)
```
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,214 @@
---
id: version-1.9.1-getting-setup
title: Getting Bitcoin-S installed on your machine
original_id: getting-setup
---
> This documentation is intended for setting up development of bitcoin-s.
> If you want to just install bitcoin-s rather than develop,
> see [getting-started](getting-started.md)
## Getting Setup With Bitcoin-S
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
<!-- END doctoc -->
- [Step 1: Developer Runtimes](#step-1--developer-runtimes)
* [Scala/Java](#scala-java)
* [Scala.js](#scalajs)
- [Step 2: Bitcoin-S Repository](#step-2--bitcoin-s-repository)
+ [Optional: Running full test suite](#optional--running-full-test-suite)
- [Step 3: Configuration](#step-3--configuration)
- [Step 4: Building the Server and Setting Up the CLI](#step-4--building-the-server-and-setting-up-the-cli)
- [Step 5: Setting Up A Bitcoin-S Node](#step-5--setting-up-a-bitcoin-s-node)
* [Neutrino Node](#neutrino-node)
* [Bitcoind Backend](#bitcoind-backend)
- [Step 6 (Optional): Moving To Testnet](#step-6--optional---moving-to-testnet)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Step 1: Developer Runtimes
### Scala/Java
You can choose to install the Scala toolchain with sdkmon or coursier.
#### Sdkman
You can install sdkman [here](https://sdkman.io/install)
Next you can install `java` and `sbt` with
```
sdk install java
sdk install sbt
```
#### Coursier
If you don't like `curl`, you can use OS specific package managers to install coursier [here](https://get-coursier.io/docs/2.0.0-RC2/cli-overview.html#installation)
>bitcoin-s requires java9+ for development environments. If you do not have java9+ installed, you will not be able to build bitcoin-s.
[You will run into this error if you are on java8 or lower](https://github.com/bitcoin-s/bitcoin-s/issues/3298)
If you follow the coursier route, [you can switch to a java11 version by running](https://get-coursier.io/docs/2.0.0-RC6-15/cli-java.html)
>cs java --jvm adopt:11 --setup
### Scala.js
We support publishing of [scala.js](https://www.scala-js.org/) artifacts.
This library will compile Scala source code into javascript artifacts.
To be able to run scala js tests, you need to have the Node.js installed.
You can install it from [here](https://nodejs.org/en/)
## Step 2: Bitcoin-S Repository
Now, it is time to clone the [Bitcoin-S repository](https://github.com/bitcoin-s/bitcoin-s/) by running
```bashrc
git clone --depth 500 --recursive git@github.com:bitcoin-s/bitcoin-s.git
```
or alternatively, if you do not have ssh setup with github, you can run
```bashrc
git clone --depth 500 --recursive https://github.com/bitcoin-s/bitcoin-s.git
```
#### Optional: Running full test suite
<details>
> WARNING: This should not be done on low resource machines. Running the entire test suite requires at minimum of 4GB
> of RAM on the machine you are running this on.
To run the entire test suite, you need to download all bitcoind instances and eclair instances. This is needed for unit tests
or binding bitcoin-s to a bitcoind instance if you do not have locally running instances.
If you want to run the entire test suite you can run the following command.
```bashrc
sbt test
```
</details>
## Step 3: Configuration
Now that we have the bitcoin-s repo setup, we want to create our application configurations.
First, create a `$HOME/.bitcoin-s` directory via `mkdir` or an equivalent command.
Next, create a `bitcoin-s.conf` file in `$HOME/.bitcoin-s`. [Here is an example configuration file](config/configuration.md#example-configuration-file).
## Step 4: Building the Server and Setting Up the CLI
We are finally ready to start running some programs! Follow the [instructions here](applications/server.md#building-the-server) to build the server.
Then, follow [these instructions](applications/cli.md) to setup the CLI.
## Step 5: Setting Up A Bitcoin-S Node
There are 2 ways to use the bitcoin-s server. It can either be as a neutrino node or use bitcoind as a backend.
This can be configured by the configuration option `bitcoin-s.node.mode` choosing either `neutrino` or `bitcoind`.
### Neutrino Node
<details>
To use a neutrino server you need to be paired with a bitcoin node that can serve compact filters.
[Suredbits](https://suredbits.com/) runs a mainnet and testnet node you can connect to them by setting your `peers` config option in the `$HOME/.bitcoin-s/bitcoin-s.conf` to:
Mainnet:
`bitcoin-s.node.peers = ["neutrino.suredbits.com:8333"]`
Testnet:
`bitcoin-s.node.peers = ["neutrino.testnet3.suredbits.com:18333"]`
If you would like to use your own node you can either use the bitcoind backend option or connect to your own compatible node.
After building your bitcoin-s server and properly configuring it to be in `neutrino` mode you can start your server with:
```bashrc
./app/server/target/universal/stage/bin/bitcoin-s-server
```
and once this is done, you should be able to communicate with the server using
```bashrc
./app/cli/target/universal/stage/bin/bitcoin-s-cli getnewaddress
```
</details>
### Bitcoind Backend
<details>
We recommend creating a directory someplace in which to run your `bitcoind` node. Once you have this directory created, add the following `bitcoin.conf` file to it:
```
regtest=1
server=1
rpcuser=[your username here]
rpcpassword=[your password here]
daemon=1
blockfilterindex=1
peerblockfilters=1
debug=1
txindex=1
```
If you already have a bitcoind node running and would like to connect your bitcoin-s server to it you can set your node's mode to `bitcoind`.
You will need to configure bitcoin-s to be able to find your bitcoind.
If you would only like bitcoin-s to connect to bitcoind and start it itself then you only need to properly set the `rpcuser`, and `rpcpassword` options.
If you would like bitcoin-s to launch bitcoind on start up you will need to set the other configuration options.
These options should default to use the latest bitcoind downloaded from `sbt downloadBitcoind`.
```$xslt
bitcoin-s {
bitcoind-rpc {
# bitcoind rpc username
rpcuser = user
# bitcoind rpc password
rpcpassword = password
# Binary location of bitcoind
binary = ${HOME}/.bitcoin-s/binaries/bitcoind/bitcoin-0.20.1/bin/bitcoind
# bitcoind datadir
datadir = ${HOME}/.bitcoin
# bitcoind network host
connect = localhost
# bitcoind p2p port
port = 8333
# bitcoind rpc host
rpcconnect = localhost
# bitcoind rpc port
rpcport = 8332
}
}
```
</details>
## Step 6 (Optional): Moving To Testnet
To run your Bitcoin-S Server on testnet, simply change `network = testnet3` and change
your `bitcoin-s.node.peers = ["neutrino.testnet3.suredbits.com:18333"] ` in your `$HOME/.bitcoin-s/bitcoin-s.conf` file.
This will allow you to connect to Suredbits' neutrino-enabled `bitcoind` node.
Keep in mind then when you restart your server, it will begin initial sync which will take
many hours as all block filters for all testnet blocks will be downloaded.
If you wish to speed this process up,
download [this snapshot](https://s3-us-west-2.amazonaws.com/www.suredbits.com/chaindb-testnet-2021-02-03.zip), unzip it and put the file in your `$HOME/.bitcoin-s/testnet3` directory and then from there, run
This will start syncing your testnet node from block header ~1,900,000 rather than starting from zero.
```bashrc
unzip chaindb-testnet-2021-02-03.zip
mv chaindb.sqlite ~/.bitcoin-s/testnet3/
```
This should take a couple minutes to execute, but once it is done, you will only have a short while left to sync once you start your server.

View file

@ -0,0 +1,127 @@
---
id: version-1.9.1-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.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-core" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-chain" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-oracle" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-eclair-rpc" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-fee-provider" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-key-manager" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-lnd-rpc" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-node" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-oracle-explorer-client" % "1.9.0"
libraryDependencies +="org.bitcoin-s" % "bitcoin-s-secp256k1jni" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit-core" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-wallet" % "1.9.0"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-zmq" % "1.9.0"
```
### 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.0-92-1613954b-20220331-0848-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.1-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, 0x276381a30efecddd373da5456f37a4f1233a418bbcd15992dcca65f43b8cb293)
val mnemonic = MnemonicCode.fromEntropy(entropy)
// mnemonic: MnemonicCode = Masked(MnemonicCodeImpl)
//you can print that mnemonic seed with this
println(mnemonic.words)
// Vector(cherry, bright, hand, bulb, under, update, table, regret, earth, keen, truck, time, crisp, camp, confirm, olive, flower, notice, crater, slogan, dry, shock, ski, kingdom)
```
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-example10762498862031068354/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-example10762498862031068354/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@79cd002f)
val rootXPub = km.right.get.getRootXPub
// rootXPub: ExtPublicKey = vpub5SLqN2bLY4WeaQShmbMMif4PSZjQQb1JQwH2dmNN1jSao51ST82VUnyXR7tHqbyriBRWrJ36Wa8cECBh95Md9Gb1Ub7fdSLcSW2vmdXuzh9
println(rootXPub)
// vpub5SLqN2bLY4WeaQShmbMMif4PSZjQQb1JQwH2dmNN1jSao51ST82VUnyXR7tHqbyriBRWrJ36Wa8cECBh95Md9Gb1Ub7fdSLcSW2vmdXuzh9
```
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-example10762498862031068354/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@4ccd8f3e
val mainnetXpub = mainnetKeyManager.getRootXPub
// mainnetXpub: ExtPublicKey = zpub6jftahH18ngZybDB72VrZ1SQ8SKCB4yJ5PMumLwuXkx71UGMTkgjy3c5VwidqEbYLjtjrCRLMDYomLdx1s1gLDKQwwuMy5cZXQHWKytsJYN
println(mainnetXpub)
// zpub6jftahH18ngZybDB72VrZ1SQ8SKCB4yJ5PMumLwuXkx71UGMTkgjy3c5VwidqEbYLjtjrCRLMDYomLdx1s1gLDKQwwuMy5cZXQHWKytsJYN
```
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,145 @@
---
id: version-1.9.1-node
title: Light Client
original_id: node
---
Bitcoin-s has node module that allows you to connect to the p2p network.
### Neutrino Node
Bitcoin-s has experimental support for neutrino which is a new lite client proposal on the bitcoin p2p network. You can
read more about how neutrino works [here](https://suredbits.com/neutrino-what-is-it-and-why-we-need-it/). At this time,
bitcoin-s only supports connecting to one trusted peer.
#### Limitations
Currently, the node does not have an active mempool.
It is only aware of transactions it broadcasts and ones confirmed in blocks.
#### Callbacks
Bitcoin-S support call backs for the following events that happen on the bitcoin p2p network:
1. onTxReceived
2. onBlockReceived
3. onMerkleBlockReceived
4. onCompactFilterReceived
That means every time one of these events happens on the p2p network, we will call your callback
so that you can be notified of the event. These callbacks will be run after the message has been
recieved and will execute sequentially. If any of them fail an error log will be output and the remainder of the callbacks will continue.
Let's make an easy one
#### Example
Here is an example of constructing a neutrino node and registering a callback so you can be notified of an event.
To run the example, we need a bitcoind binary that has neutrino support.
Bitcoin Core only has p2p neutrino support as of version 0.21.0.
You will need to use a version of Bitcoin Core at least as old as 0.21.0.
For your node to be able to service these filters you will need set
`blockfilterindex=1` and `peerblockfilters=1` in your `bitcoin.conf` file.
```scala
implicit val system = ActorSystem(s"node-example")
implicit val ec = system.dispatcher
//we also require a bitcoind instance to connect to
//so let's start one (make sure you ran 'sbt downloadBitcoind')
val instance = BitcoindRpcTestUtil.instance(versionOpt = Some(BitcoindVersion.Experimental))
val p2pPort = instance.p2pPort
val bitcoindF = BitcoindRpcTestUtil.startedBitcoindRpcClient(Some(instance), Vector.newBuilder)
//contains information on how to connect to bitcoin's p2p info
val peerF = bitcoindF.flatMap(b => NodeUnitTest.createPeer(b))
// set a data directory
val prefix = s"node-example-${System.currentTimeMillis()}"
val datadir = Files.createTempDirectory(prefix)
val tmpDir = BitcoinSTestAppConfig.tmpDir()
// set the current network to regtest
val config = ConfigFactory.parseString {
s"""
| bitcoin-s {
| network = regtest
| node {
| mode = neutrino # neutrino, spv
|
| peers = ["127.0.0.1:$p2pPort"] # a list of peer addresses in form "hostname:portnumber"
| # (e.g. "neutrino.testnet3.suredbits.com:18333")
| # Port number is optional, the default value is 8333 for mainnet,
| # 18333 for testnet and 18444 for regtest.
| }
| }
|""".stripMargin
}
implicit val appConfig = BitcoinSAppConfig(datadir, Vector(config))
implicit val chainConfig = appConfig.chainConf
implicit val nodeConfig = appConfig.nodeConf
val initNodeF = nodeConfig.start()
//the node requires a chainHandler to store block information
//use a helper method in our testkit to create the chain project
val chainApiF = for {
chainHandler <- ChainUnitTest.createChainHandler()
} yield chainHandler
//yay! All setup done, let's create a node and then start it!
val nodeF = for {
chainApi <- chainApiF
peer <- peerF
} yield {
//you can set this to only sync compact filters after the timestamp
val walletCreationTimeOpt = None
val dataMessageHandler = DataMessageHandler(chainApi, walletCreationTimeOpt)
NeutrinoNode(configPeersOverride = Vector(peer),
dataMessageHandler = dataMessageHandler,
nodeConfig = nodeConfig,
chainConfig = chainConfig,
actorSystem = system)
}
//let's start it
val startedNodeF = nodeF.flatMap(_.start())
//let's make a simple callback that print's the
//blockhash everytime we receive a block on the network
val blockReceivedFunc: OnBlockReceived = { block: Block =>
Future.successful(
println(s"Received blockhash=${block.blockHeader.hashBE}"))
}
// Create callback
val nodeCallbacks = NodeCallbacks.onBlockReceived(blockReceivedFunc)
// Add call to our node's config
nodeConfig.addCallbacks(nodeCallbacks)
//let's test it out by generating a block with bitcoind!
val genBlockF = for {
bitcoind <- bitcoindF
addr <- bitcoind.getNewAddress
hashes <- bitcoind.generateToAddress(1,addr)
} yield hashes
//you should see our callback print a block hash
//when running this code
//cleanup
val cleanupF = for {
_ <- genBlockF
bitcoind <- bitcoindF
node <- startedNodeF
x = NeutrinoNodeConnectedWithBitcoind(node.asInstanceOf[NeutrinoNode],bitcoind)
_ <- NodeUnitTest.destroyNodeConnectedWithBitcoind(x)
} yield ()
Await.result(cleanupF, 60.seconds)
```

View file

@ -0,0 +1,212 @@
---
id: version-1.9.1-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.1-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(03e74700b3e4b7dc63fd6da49ea5af0d3baa0896616e97ff422d8cbd9a3e7f23da)
val dataToSign = DoubleSha256Digest.empty
// dataToSign: DoubleSha256Digest = DoubleSha256Digest(0000000000000000000000000000000000000000000000000000000000000000)
// calls bouncy castle indirectly via CryptoContext
val signature = privKey.sign(dataToSign.bytes)
// signature: ECDigitalSignature = ECDigitalSignature(3045022100def00773f8a70da2170cfc7070036fd759670a1f7d8c91f44e6240c21c15d63c022076343b612c8529a8cc75fe0c5ca1ed7ef5af5b0f24b8fa47ebd8ebae6d41c3a7)
// 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,95 @@
---
id: version-1.9.1-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
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 git@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,322 @@
---
id: version-1.9.1-dlc
title: Executing A DLC with Bitcoin-S
original_id: dlc
---
## Executing A Discreet Log Contract (DLC)
## Step 1: Get Bitcoin-S Setup
See the [setup document](../getting-setup.md).
### Using the GUI
To first start up the GUI you first need to start your bitcoin-s server and gui with
```bashrc
sbt bundle/run
```
or if your bitcoin-s server is already running, you can run the standalone gui with
```bashrc
sbt gui/run
```
or by following the instructions for building and running the GUI [here](../getting-setup.md#step-5-setting-up-a-bitcoin-s-server)
## Step 2: Agree On Contract Terms
Both parties must agree on all fields from the table below:
| Field Name | Description |
| :------------: | :------------------------------------------------------: |
| contractInfo | Information about payouts and which oracles to use |
| collateral | Number of sats the initiator is putting up |
| locktime | Locktime of the CETs |
| refundlocktime | Locktime of the Refund Transaction |
| feerate | Fee rate in sats/vbyte |
> Note: if you wish to set up your own oracle for testing, you can do so by checking out our [oracle rpc server](../oracle/oracle-server.md) or [Krystal Bull](https://github.com/bitcoin-s/krystal-bull)
### Decoding DLC Messages
With the cli tool you can decode dlc offers, contract infos, oracle announcements, and oracle attestations.
This can be helpful for when developing on top of bitcoin-s and not having the proper DLC tooling to understand the messages.
Examples:
Decoding Offer:
```bash
bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82ee40000000000010f2cfda7101802035965730000000000010f2c024e6f0000000000000000fda712bcfdd824b8d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68fdd822540001ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f60dfa880fdd80609000203596573024e6f20446f657320746865206d656d706f6f6c20636c656172206f6e20372f322f323102279cf17c387d7101b08d90b2aeef46231957d9d3558f5871e62781a68e7d75c9001600148dc81a3097bf28c6020eaf89cefae69c5f31aceb5d655d867008d23e00000000000090880001fda714fd01b3627231e09b7948c3019d02000000000102368af13baeef5a313d3ef12e895b232f1e76212cb76957d7e4b8a664915d15960100000000fdfffffffaec4ef43ae2365d0abc53336188053da4078a5b7489928602bcc8c9a4b75f0d0000000000fdffffff030f0b000000000000160014107eb2463ad25843ed01fd33656c83bdd11db3554a8701000000000022002002265c41f299b3c7f0dda5b9d7bc4135d25c2d8aed286837aa9e0954d70894d606961c000000000016001482a7ecd4624e6856d1b09c27e9f3a82323f49c2d0247304402200911162e99e23e4a26e0219a4bdaaf7a5f790be63a8376516640dcc0860ca4d602203a078371904842e2e6adfbebebcac138db23514b3396851569f5f2bf82c3197a012103cd2d0a4eace5993ebb0a75da85d9070627e64f1a5783cf5217e9bd82d20d1c470247304402200fa8515323410ca2b14b08bf22c618b6ced77b9289cb1dfa7ac10548e2e1b2e002206a407bcafdfb64009182fb5838db9671968abdd902e1194f6883cd0e5413ad36012103d3864eb755690e2b4ff139047419373e36a05630429da76fef5de25eeffb4ffc0000000000000002fffffffd006b000000160014d13be5f330b1ea9bbf61f68002b4465e02c341d9df27e1460161e002825311ec94d1e91b000000000000000a0000000061316580
{
"contractFlags": "0",
"chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000",
"contractInfo": {
"totalCollateral": 69420,
"contractDescriptor": {
"outcomes": [
{
"outcome": "Yes",
"localPayout": 69420
},
{
"outcome": "No",
"localPayout": 0
}
]
},
"oracleInfo": {
"announcement": {
"announcementSignature": "d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2",
"publicKey": "b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68",
"event": {
"nonces": [
"ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f"
],
"maturity": "2021-07-03T00:00:00Z",
"descriptor": {
"outcomes": [
"Yes",
"No"
]
},
"eventId": "Does the mempool clear on 7/2/21"
}
}
}
},
"fundingPubKey": "02279cf17c387d7101b08d90b2aeef46231957d9d3558f5871e62781a68e7d75c9",
"payoutSPK": "1600148dc81a3097bf28c6020eaf89cefae69c5f31aceb",
"payoutSerialId": 6729888050161701888,
"offerCollateral": 37000,
"fundingInputs": [
{
"inputSerialId": 7093787203812804608,
"prevTx": "02000000000102368af13baeef5a313d3ef12e895b232f1e76212cb76957d7e4b8a664915d15960100000000fdfffffffaec4ef43ae2365d0abc53336188053da4078a5b7489928602bcc8c9a4b75f0d0000000000fdffffff030f0b000000000000160014107eb2463ad25843ed01fd33656c83bdd11db3554a8701000000000022002002265c41f299b3c7f0dda5b9d7bc4135d25c2d8aed286837aa9e0954d70894d606961c000000000016001482a7ecd4624e6856d1b09c27e9f3a82323f49c2d0247304402200911162e99e23e4a26e0219a4bdaaf7a5f790be63a8376516640dcc0860ca4d602203a078371904842e2e6adfbebebcac138db23514b3396851569f5f2bf82c3197a012103cd2d0a4eace5993ebb0a75da85d9070627e64f1a5783cf5217e9bd82d20d1c470247304402200fa8515323410ca2b14b08bf22c618b6ced77b9289cb1dfa7ac10548e2e1b2e002206a407bcafdfb64009182fb5838db9671968abdd902e1194f6883cd0e5413ad36012103d3864eb755690e2b4ff139047419373e36a05630429da76fef5de25eeffb4ffc00000000",
"prevTxVout": 2,
"sequence": 4294967293,
"maxWitnessLen": 107,
"redeemScript": null
}
],
"changeSPK": "160014d13be5f330b1ea9bbf61f68002b4465e02c341d9",
"changeSerialId": 1.6080068685336797E19,
"fundOutputSerialId": 9.390869355804355E18,
"feeRatePerVb": 10,
"cetLocktime": 0,
"refundLocktime": 1630627200
}
```
Decoding Contract Info:
```bash
bitcoin-s-cli decodecontractinfo fdd82ee40000000000010f2cfda7101802035965730000000000010f2c024e6f0000000000000000fda712bcfdd824b8d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68fdd822540001ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f60dfa880fdd80609000203596573024e6f20446f657320746865206d656d706f6f6c20636c656172206f6e20372f322f3231
{
"totalCollateral": 69420,
"contractDescriptor": {
"outcomes": [
{
"outcome": "Yes",
"localPayout": 69420
},
{
"outcome": "No",
"localPayout": 0
}
]
},
"oracleInfo": {
"announcement": {
"announcementSignature": "d89fe4d84bdf96299d2e3664acda7e14001297f341afcaca91d3909f12988cb308f309625d89c078bf2268b174faf1c082f1f10bef55834af50b91d9a241ffb2",
"publicKey": "b8b005b07acf849ad2cec22107331dedbf5a607654fad4eafe39c278e27dde68",
"event": {
"nonces": [
"ef8bd9f4445543c63923dde8c00f60d649c445a7772ac4693136b2fd234fcc2f"
],
"maturity": "2021-07-03T00:00:00Z",
"descriptor": {
"outcomes": [
"Yes",
"No"
]
},
"eventId": "Does the mempool clear on 7/2/21"
}
}
}
```
Decoding Oracle Announcement:
```bash
bitcoin-s-cli decodeannouncement fdd824b1585e18c3bc1d922854329fdb5a402713b161b7baebb6b6f3249936ef79c0a6671027afd7a1126d79e589811042eb4885c0cb7c150b4c4863a1e35a2ac432f7c81d5dcdba2e64cb116cc0c375a0856298f0058b778f46bfe625ac6576204889e4fdd8224d0001424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474603c2e80fdd80609000203594553024e4f194254432d5553442d4f5645522d35304b2d434f494e42415345
{
"announcementSignature": "585e18c3bc1d922854329fdb5a402713b161b7baebb6b6f3249936ef79c0a6671027afd7a1126d79e589811042eb4885c0cb7c150b4c4863a1e35a2ac432f7c8",
"publicKey": "1d5dcdba2e64cb116cc0c375a0856298f0058b778f46bfe625ac6576204889e4",
"event": {
"nonces": [
"424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474"
],
"maturity": "2021-03-01T00:00:00Z",
"descriptor": {
"outcomes": [
"YES",
"NO"
]
},
"eventId": "BTC-USD-OVER-50K-COINBASE"
}
}
```
Decoding Oracle Attestations
```bash
bitcoin-s-cli decodeattestments fdd8687f194254432d5553442d4f5645522d35304b2d434f494e424153451d5dcdba2e64cb116cc0c375a0856298f0058b778f46bfe625ac6576204889e40001424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474de6b75f1da183a2a4f9ad144b48bf1026cee9687221df58f04128db79ca17e2a024e4f
{
"eventId": "BTC-USD-OVER-50K-COINBASE",
"signatures": [
"424c11a44c2e522f90bbe4abab6ec1bc8ab44c9b29316ce6e1d0d7d08385a474de6b75f1da183a2a4f9ad144b48bf1026cee9687221df58f04128db79ca17e2a"
],
"values": [
"NO"
]
}
```
## Step 3: Set up The DLC
### Using the GUI
If you're a visual learner there is a [video demo](https://www.youtube.com/watch?v=zy1sL2ndcDg) that explains this process in detail.
But do note that this demonstrates the old non-adaptor version of DLCs so that the Offer, Accept, Sign protocol is the same, but the contents will be different.
If using a numeric contract and/or multiple oracles, messages can get very large and sometimes even too large to for the application.
To solve this there is an `Export to file` button located under the text box for the messages your wallet will construct.
This can be used to export a DLC message to a file and then the file can be sent to your counterparty.
If you receive a file from a counter-party, there is an `Import file` button on every dialog you input a DLC message.
This can be used to import the file of the DLC message from your counter-party.
#### Creating The Offer
Once the terms are agreed to, either party can use the `Offer` button and enter each of the fields from the table above.
#### Accepting The Offer
Upon receiving a DLC Offer from your counter-party, you can use the `Accept` button and paste in the DLC Offer.
#### Signing The DLC
Upon receiving a DLC Accept message from your counter-party, you can use the `Sign` button and paste in the DLC Accept.
#### Adding DLC Signatures To Your Database
Upon receiving a DLC Sign message from your counter-party, add their signatures to your database using the `Add Sigs` button and paste in the message.
After doing so you can get the fully signed funding transaction using the `Get Funding Tx` button. This will return the fully signed serialized transaction.
### Using the CLI
If using a numeric contract and/or multiple oracles, messages can get very large and sometimes even too large to for the application.
To solve this there are RPC calls where you can give a file instead of the entire DLC message.
To output a file you simply just need to pipe the output of a command into a file.
For example:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli acceptdlcoffer [offer] > myDLCAccept.txt
```
#### Creating The Offer
Once these terms are agreed to, either party can call on `createdlcoffer` with flags for each of the fields in the table above. For example:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli createdlcoffer [contractInfo] [collateral] [feerate] [locktime] [refundlocktime]
```
#### Accepting The Offer
Upon receiving a DLC Offer from your counter-party, the following command will create the serialized accept message:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli acceptdlcoffer [offer]
```
or from file:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli acceptdlcofferfromfile [filepath]
```
#### Signing The DLC
Upon receiving a DLC Accept message from your counter-party, the following command will generate all of your signatures for this DLC:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli signdlc [accept]
```
or from file:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli signdlcfromfile [filepath]
```
#### Adding DLC Signatures To Your Database
Upon receiving a DLC Sign message from your counter-party, add their signatures to your database by:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli adddlcsigs [sign]
```
or from file:
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli adddlcsigsfromfile [filepath]
```
#### Getting Funding Transaction
You are now fully setup and can generate the fully signed funding transaction for broadcast using
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli getdlcfundingtx [contractId]
```
where the `contractId` is in all but the messages other than the DLC Offer message, and is also returned by the `adddlcsigs` command.
Alternatively, you can use the `getdlcs` command to list all of your current DLCs saved in your wallet.
## Step 4: Executing the DLC
### Using the GUI
#### Execute
You can execute the DLC unilaterally with the `Execute` button which will require the oracle signature.
This will return a fully signed Contract Execution Transaction for the event signed by the oracle.
#### Refund
If the `refundlocktime` for the DLC has been reached, you can get the fully-signed refund transaction with the `Refund` button and entering the `contractId`.
### Using the CLI
#### Execute
Upon receiving an oracle signature, you can execute the DLC unilaterally with
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli executedlc [contractId] [signatureTLVs]
```
which will return fully signed Contract Execution Transaction for the event signed by the oracle.
#### Refund
If the `refundlocktime` for the DLC has been reached, you can get the fully-signed refund transaction with
```bashrc
./app/cli/target/universal/stage/bitcoin-s-cli executedlcrefund [contractId]
```

View file

@ -0,0 +1,321 @@
---
id: version-1.9.1-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. locktime
5. refund locktime
As of this writing, the current block height is `703,401`. For the sake of this example
I'm going to pick a `locktime=0` and a refund locktime 2 weeks in advance `refundLocktime=705417`
Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral.
```
./bitcoin-s-cli createdlcoffer fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e \
60000 \
1 \
0 \
705417
a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389
```
Yay! We have now created an offer (`a71a006fe...`) that we can send to our counterparty, Bob. If you would like to review
the offer before sending it to him you can use `decodeoffer`
```
./bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389
{
"contractFlags": "0",
"chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000",
"contractInfo": {
"totalCollateral": 100000,
"contractDescriptor": {
"outcomes": {
"Republican_win": 0,
"Democrat_win": 100000,
"other": 60000
}
},
"oracleInfo": {
"announcement": {
"announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5",
"publicKey": "d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a",
"event": {
"nonces": [
"ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14"
],
"maturity": "2021-02-02T00:00:00Z",
"descriptor": {
"outcomes": [
"Republican_win",
"Democrat_win",
"other"
]
},
"eventId": "2020-us-election"
}
}
}
},
"fundingPubKey": "02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0",
"payoutSPK": "1600141df0a84b2d2e611dd595101bfed6320143c47ebb",
"payoutSerialId": 1.2572776984081695E19,
"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,411 @@
---
id: version-1.9.1-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. locktime
5. refund locktime
As of this writing, the current block height is `705161` . For the sake of this example
I'm going to pick a `locktime=0` and a refund locktime 2 weeks in advance `refundLocktime=707177`
Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral.
```
./bitcoin-s-cli createdlcoffer fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \
50000 \
1 \
0 \
> 707177 \
a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69
```
You can decode the offer above with `decodeoffer`
```
./bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69
{
"contractFlags": "0",
"chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000",
"contractInfo": {
"totalCollateral": 100000,
"contractDescriptor": {
"numDigits": 17,
"payoutFunction": {
"points": [
{
"outcome": 0,
"payout": 0,
"extraPrecision": 0,
"isEndpoint": true
},
{
"outcome": 40000,
"payout": 0,
"extraPrecision": 0,
"isEndpoint": true
},
{
"outcome": 42500,
"payout": 50000,
"extraPrecision": 0,
"isEndpoint": true
},
{
"outcome": 45000,
"payout": 100000,
"extraPrecision": 0,
"isEndpoint": true
},
{
"outcome": 131071,
"payout": 100000,
"extraPrecision": 0,
"isEndpoint": true
}
]
},
"roundingIntervals": {
"intervals": []
}
},
"oracleInfo": {
"announcement": {
"announcementSignature": "659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e5703",
"publicKey": "0574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949",
"event": {
"nonces": [
"4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6",
"588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274",
"a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd",
"166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e",
"88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2",
"238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88",
"a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5",
"719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433",
"7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3",
"ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f",
"853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d",
"1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84",
"cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c",
"104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab6669983",
"2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968",
"aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82",
"ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d"
],
"maturity": "2021-02-04T00:00:00Z",
"descriptor": {
"base": 2,
"isSigned": false,
"unit": "BTC/USD",
"precision": 0
},
"eventId": "bitcoin-s-price-example"
}
}
}
},
"fundingPubKey": "03a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33",
"payoutSPK": "1600148cd33b6fadc74aaca3982d3fd1891b1100a01e99",
"payoutSerialId": 7520084828858968064,
"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

@ -0,0 +1,52 @@
---
title: Wallet RPC Examples
id: version-1.9.1-wallet-rpc
original_id: wallet-rpc
---
### `listreservedutxos`
Lists all reserved utxos in the wallet.
These utxos will not be unreserved unless you manually
unreserve them with `lockunspent` or they are spent in the blockchain
```bash
bitcoin-s-cli listreservedutxos
[
{
"outpoint": {
"txid": "1c22634fa282e71866a8b8c6732ec89eb5c46d30f9773486b0ae32770e8109e1",
"vout": 1,
},
"value": 2000
},
{
"outpoint": {
"txid": "2b12634fa282e71866a8b8c6732ec89eb5c46d30f9773486b0ae32770e810901",
"vout": 0,
},
"value": 1000
}
]
```
### `lockunspent`
Locks all utxos in the wallet
```bash
bitcoin-s-cli lockunspent false
```
Unlocks utxo `1c22634fa282e71866a8b8c6732ec89eb5c46d30f9773486b0ae32770e8109e1:1`
```bash
bitcoin-s-cli lockunspent true '{"txid" : "1c22634fa282e71866a8b8c6732ec89eb5c46d30f9773486b0ae32770e8109e1","vout" : 1}'
```
Locks utxos `1c22634fa282e71866a8b8c6732ec89eb5c46d30f9773486b0ae32770e8109e1:1` and `4c63268a688d103caeb26137cecd4053566bd3626504e079055581c104c4de5b:0`
```bash
bitcoin-s-cli lockunspent false '[{"txid" : "1c22634fa282e71866a8b8c6732ec89eb5c46d30f9773486b0ae32770e8109e1","vout" : 1}, {"txid" : "4c63268a688d103caeb26137cecd4053566bd3626504e079055581c104c4de5b","vout" : 0}]'
```

View file

@ -0,0 +1,99 @@
{
"version-1.9.1-docs": {
"Getting Started": [
"version-1.9.1-getting-started",
"version-1.9.1-bips"
],
"Getting Setup": [
"version-1.9.1-getting-setup",
"version-1.9.1-ui-setup"
],
"Applications": [
"version-1.9.1-applications/cli",
"version-1.9.1-applications/server",
"version-1.9.1-applications/gui",
"version-1.9.1-applications/server-systemd"
],
"Chain": [
"version-1.9.1-chain/chain",
"version-1.9.1-chain/filter-sync",
"version-1.9.1-chain/chain-query-api"
],
"Configuration": [
"version-1.9.1-config/configuration"
],
"Core Module": [
"version-1.9.1-core/core-intro",
"version-1.9.1-core/addresses",
"version-1.9.1-core/hd-keys",
"version-1.9.1-core/adding-spks",
"version-1.9.1-core/spending-info",
"version-1.9.1-core/psbts",
"version-1.9.1-core/dlc",
"version-1.9.1-core/txbuilder",
"version-1.9.1-core/lightning-network"
],
"Crypto Module": [
"version-1.9.1-crypto/crypto-intro",
"version-1.9.1-crypto/sign",
"version-1.9.1-crypto/adaptor-signatures"
],
"Fee Provider": [
"version-1.9.1-fee-provider/fee-provider"
],
"Key Manager": [
"version-1.9.1-key-manager/server-key-manager",
"version-1.9.1-key-manager/key-manager"
],
"Node": [
"version-1.9.1-node/node",
"version-1.9.1-node/node-api"
],
"Wallet": [
"version-1.9.1-wallet/wallet",
"version-1.9.1-wallet/wallet-callbacks",
"version-1.9.1-wallet/wallet-get-address",
"version-1.9.1-wallet/address-tagging",
"version-1.9.1-wallet/dlc",
"version-1.9.1-wallet/wallet-rescan",
"version-1.9.1-wallet/wallet-sync",
"version-1.9.1-wallet/wallet-rpc",
"version-1.9.1-wallet/backups",
"version-1.9.1-wallet/wallet-election-example",
"version-1.9.1-wallet/wallet-price-example"
],
"Tor": [
"version-1.9.1-tor/tor"
],
"RPC Clients": [
"version-1.9.1-rpc/rpc-clients-intro",
"version-1.9.1-rpc/rpc-eclair",
"version-1.9.1-rpc/rpc-bitcoind",
"version-1.9.1-rpc/lnd-rpc"
],
"Secp256k1": [
"version-1.9.1-secp256k1/secp256k1",
"version-1.9.1-secp256k1/jni-modify"
],
"Testkit": [
"version-1.9.1-testkit/testkit",
"version-1.9.1-testkit/testkit-core"
],
"DLC Oracle": [
"version-1.9.1-oracle/build-oracle-server",
"version-1.9.1-oracle/oracle-server",
"version-1.9.1-oracle/oracle-election-example",
"version-1.9.1-oracle/oracle-price-example"
],
"Oracle Explorer Client": [
"version-1.9.1-oracle-explorer-client/oracle-explorer-client"
],
"Contributing": [
"version-1.9.1-contributing",
"version-1.9.1-contributing-website"
],
"Security": [
"version-1.9.1-security"
]
}
}

View file

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