mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-22 14:33:06 +01:00
1.9.2 website (#4390)
This commit is contained in:
parent
52ded677e0
commit
678c29cf81
19 changed files with 3039 additions and 0 deletions
|
@ -1021,6 +1021,57 @@
|
|||
},
|
||||
"version-1.9.1/wallet/version-1.9.1-wallet-rpc": {
|
||||
"title": "Wallet RPC Examples"
|
||||
},
|
||||
"version-1.9.2/applications/version-1.9.2-cli": {
|
||||
"title": "CLI"
|
||||
},
|
||||
"version-1.9.2/applications/version-1.9.2-server": {
|
||||
"title": "Application Server"
|
||||
},
|
||||
"version-1.9.2/chain/version-1.9.2-chain-query-api": {
|
||||
"title": "Chain Query API"
|
||||
},
|
||||
"version-1.9.2/core/version-1.9.2-addresses": {
|
||||
"title": "Generating Addresses"
|
||||
},
|
||||
"version-1.9.2/core/version-1.9.2-dlc": {
|
||||
"title": "Discreet Log Contract Data Structures"
|
||||
},
|
||||
"version-1.9.2/core/version-1.9.2-hd-keys": {
|
||||
"title": "HD Key Generation"
|
||||
},
|
||||
"version-1.9.2/core/version-1.9.2-txbuilder": {
|
||||
"title": "TxBuilder Example"
|
||||
},
|
||||
"version-1.9.2/crypto/version-1.9.2-sign": {
|
||||
"title": "Sign API"
|
||||
},
|
||||
"version-1.9.2/version-1.9.2-getting-started": {
|
||||
"title": "Intro and Getting Started"
|
||||
},
|
||||
"version-1.9.2/key-manager/version-1.9.2-key-manager": {
|
||||
"title": "Key Manager"
|
||||
},
|
||||
"version-1.9.2/node/version-1.9.2-node-api title: Node API": {
|
||||
"title": "node-api title: Node API"
|
||||
},
|
||||
"version-1.9.2/oracle/version-1.9.2-oracle-server": {
|
||||
"title": "Oracle Server"
|
||||
},
|
||||
"version-1.9.2/secp256k1/version-1.9.2-secp256k1": {
|
||||
"title": "Secp256k1"
|
||||
},
|
||||
"version-1.9.2/version-1.9.2-security": {
|
||||
"title": "Security"
|
||||
},
|
||||
"version-1.9.2/version-1.9.2-ui-setup": {
|
||||
"title": "Installing the DLC Wallet UI"
|
||||
},
|
||||
"version-1.9.2/wallet/version-1.9.2-wallet-election-example": {
|
||||
"title": "Wallet Election Example"
|
||||
},
|
||||
"version-1.9.2/wallet/version-1.9.2-wallet-price-example": {
|
||||
"title": "Wallet Price Example"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
|
64
website/versioned_docs/version-1.9.2/applications/cli.md
Normal file
64
website/versioned_docs/version-1.9.2/applications/cli.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
id: version-1.9.2-cli
|
||||
title: CLI
|
||||
original_id: cli
|
||||
---
|
||||
|
||||
|
||||
## Bitcoin-s command line interface
|
||||
|
||||
The [cli](/api/org/bitcoins/cli) project is meant to be a bitcoin-s command line interface (cli).
|
||||
|
||||
You only need to do one of the two sections below (Building the command line interface) or (Native binaries), and we recommend doing the first option because it is simpler.
|
||||
|
||||
### Building the command line interface
|
||||
|
||||
You must first have [bitcoin-s properly installed](../getting-setup) on your machine, after which you should be able to build the cli with
|
||||
```bashrc
|
||||
sbt cli/universal:stage
|
||||
```
|
||||
|
||||
After running that command you should find the executable here:
|
||||
|
||||
```bash
|
||||
./app/cli/target/universal/stage/bin/bitcoin-s-cli
|
||||
```
|
||||
|
||||
### Executing commands
|
||||
You can ask the client for help with
|
||||
|
||||
```bash
|
||||
./app/cli/target/universal/stage/bin/bitcoin-s-cli --help
|
||||
Usage: bitcoin-s-cli [options] [<cmd>]
|
||||
|
||||
-n, --network <value> Select the active network.
|
||||
--debug Print debugging information
|
||||
-h, --help Display this help message and exit
|
||||
<cmd> The command and arguments to be executed. Try bitcoin-s-cli help for a list of all commands
|
||||
```
|
||||
|
||||
|
||||
Now you are are ready to start the server that the cli sends commands to. Take a look at our [server](server.md) documentation on how to build and start the server.
|
||||
|
||||
### Native binaries
|
||||
|
||||
Bitcoin-s also supports building native executables for various platforms supported by the [graalvm native image](https://www.graalvm.org/reference-manual/native-image/) tool.
|
||||
|
||||
You can build by using the [native image plugin for sbt](https://github.com/scalameta/sbt-native-image). This will download the appropriate graalvm
|
||||
version and the native image tool, and then build the cli
|
||||
|
||||
```bashrc
|
||||
sbt cli/nativeImage
|
||||
```
|
||||
|
||||
After the build is done, you can find the artifact here locally
|
||||
|
||||
```bashrc
|
||||
app/cli/target/native-image/bitcoin-s-cli
|
||||
```
|
||||
|
||||
We also publish native image binaries every time we merge a commit to master on github.
|
||||
As an example, you can [see the artifacts](https://github.com/bitcoin-s/bitcoin-s/actions?query=workflow%3A%22Native+Image+bitcoin-s-cli%22)
|
||||
in the upper right hand corner.
|
||||
|
||||
If you don't want to build the `bitcoin-s-cli` yourself, you can download it for your platform there.
|
399
website/versioned_docs/version-1.9.2/applications/server.md
Normal file
399
website/versioned_docs/version-1.9.2/applications/server.md
Normal file
|
@ -0,0 +1,399 @@
|
|||
---
|
||||
id: version-1.9.2-server
|
||||
title: Application Server
|
||||
original_id: server
|
||||
---
|
||||
|
||||
|
||||
## App server
|
||||
|
||||
The server project is the aggregation of these three sub projects
|
||||
|
||||
1. [Wallet](../wallet/wallet.md)
|
||||
2. [Chain](../chain/chain.md)
|
||||
3. [Node](../node/node.md)
|
||||
|
||||
The server project provides a away to access information from these three projects via a JSON RPC.
|
||||
|
||||
## Building the server
|
||||
|
||||
### Java binary
|
||||
You can build the server with the [sbt native packager](https://github.com/sbt/sbt-native-packager).
|
||||
The native packager offers [numerous ways to package the project](https://github.com/sbt/sbt-native-packager#examples).
|
||||
|
||||
In this example we are going to use `stage` which will produce bash scripts we can easily execute. You can stage the server with the following command.
|
||||
|
||||
```bash
|
||||
sbt appServer/universal:stage
|
||||
```
|
||||
|
||||
This will produce a script to execute bitcoin-s which you can start with
|
||||
|
||||
```bash
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
The oracle server also has docker support. You can build a docker image with the following commands
|
||||
|
||||
#### Using an existing docker image
|
||||
|
||||
We publish docker images on every PR that is merged to bitcoin-s.
|
||||
|
||||
You can find the docker repo for the app server [here](https://hub.docker.com/r/bitcoinscala/bitcoin-s-server/tags?page=1&ordering=last_updated)
|
||||
|
||||
#### Building a docker image
|
||||
```
|
||||
sbt "appServer/docker:stage"
|
||||
```
|
||||
|
||||
This will build a `Dockerfile` that is located in `app/server/target/docker/stage`
|
||||
|
||||
You can now build the docker image with
|
||||
|
||||
```
|
||||
docker build app/server/target/docker/stage/ -t bitcoinscala/bitcoin-s-server:latest
|
||||
```
|
||||
|
||||
Finally, let's run the image! It's important that you correctly configure port forwarding with the docker container so
|
||||
you can interact with the running container with `bitcoin-s-cli` or `curl`. By default, our oracle
|
||||
server listens for requests on port `9999`. By default, the server listens for websocket connections on port `19999` at `/events`.
|
||||
|
||||
This means we need to forward requests on the host machine to the docker container correctly.
|
||||
|
||||
This can be done with the following command
|
||||
```
|
||||
docker run -d -p 9999:9999 -p 19999:19999 -e BITCOIN_S_SERVER_RPC_PASSWORD='topsecret' bitcoinscala/bitcoin-s-server:latest
|
||||
```
|
||||
|
||||
Now you can send requests with `bitcoin-s-cli` or `curl`.
|
||||
Here is an example with `bitcoin-s-cli`
|
||||
```
|
||||
./bitcoin-s-cli getblockcount --password topsecret
|
||||
10000
|
||||
```
|
||||
|
||||
For more information on build configuration options with `sbt` please see the [sbt native packager docs](https://sbt-native-packager.readthedocs.io/en/latest/formats/docker.html#tasks)
|
||||
|
||||
## Configuration
|
||||
|
||||
### Java binary configuration
|
||||
If you would like to pass in a custom datadir for your server, you can do
|
||||
|
||||
```bash
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server --datadir /path/to/datadir/
|
||||
```
|
||||
|
||||
To use a config file that is not the `bitcoin-s.conf` file in your datadir, you can do
|
||||
|
||||
```bash
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server --conf /path/to/file.conf
|
||||
```
|
||||
|
||||
You can also pass in a custom `rpcport` to bind to
|
||||
|
||||
```bash
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server --rpcport 12345
|
||||
```
|
||||
|
||||
Or set a custom `wsport` to bind to
|
||||
|
||||
```bash
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server --wsport 54321
|
||||
```
|
||||
|
||||
For more information on configuring the server please see our [configuration](../config/configuration.md) document
|
||||
|
||||
For more information on how to use our built in `cli` to interact with the server please see [cli.md](cli.md)
|
||||
|
||||
### Docker configuration
|
||||
|
||||
In this example, we are using the latest docker image published to our [docker hub](https://hub.docker.com/repository/docker/bitcoinscala/bitcoin-s-oracle-server/tags?page=1&ordering=last_updated)
|
||||
which is referenced by `bitcoinscala/bitcoin-s-server:latest`
|
||||
|
||||
You can use bitcoin-s with docker volumes. You can also pass in a custom configuration at container runtime.
|
||||
|
||||
#### Using a docker volume
|
||||
|
||||
```basrc
|
||||
docker volume create bitcoin-s
|
||||
docker run -p 9999:9999 -p 19999:19999 \
|
||||
--mount source=bitcoin-s,target=/home/bitcoin-s/ bitcoinscala/bitcoin-s-server:latest
|
||||
```
|
||||
|
||||
Now you can re-use this volume across container runs. It will keep the same oracle database
|
||||
and seeds directory located at `/home/bitcoin-s/.bitcoin-s/seeds` in the volume.
|
||||
|
||||
#### Using a custom bitcoin-s configuration with docker
|
||||
|
||||
You can also specify a custom bitcoin-s configuration at container runtime.
|
||||
You can mount the configuration file on the docker container and that
|
||||
configuration will be used in the docker container runtime rather than
|
||||
the default one we provide [here](https://github.com/bitcoin-s/bitcoin-s/blob/master/app/oracle-server/src/universal/docker-application.conf)
|
||||
|
||||
You can do this with the following command
|
||||
|
||||
```bashrc
|
||||
docker run -p 9999:9999 -p 19999:19999 \
|
||||
--mount type=bind,source=/my/new/config/,target=/home/bitcoin-s/.bitcoin-s/ \
|
||||
bitcoinscala/bitcoin-s-server:latest --conf /home/bitcoin-s/.bitcoin-s/bitcoin-s.conf
|
||||
```
|
||||
|
||||
Note: If you adjust the `bitcoin-s.server.rpcport` setting you will need to adjust
|
||||
the `-p 9999:9999` port mapping on the docker container to adjust for this.
|
||||
|
||||
## Server Endpoints
|
||||
|
||||
### Common
|
||||
- `getversion` - The version of our application you are using
|
||||
- `zipdatadir` `location` - Backs up the datadir in a safe and consistent manner.
|
||||
- `location` - The locations of the backup zip
|
||||
|
||||
### Blockchain
|
||||
- `getblockcount` - Get the current block height
|
||||
- `getfiltercount` - Get the number of filters
|
||||
- `getfilterheadercount` - Get the number of filter headers
|
||||
- `getbestblockhash` - Get the best block hash
|
||||
- `getblockheader` - Returns information about block header <hash>
|
||||
- `hash` - The block hash
|
||||
- `decoderawtransaction` `tx` - `Decode the given raw hex transaction`
|
||||
- `tx` - Transaction encoded in hex to decode
|
||||
- `getmediantimepast` - Returns the median time past
|
||||
|
||||
### Wallet
|
||||
- `rescan` `[options]` - Rescan for wallet UTXOs
|
||||
- `--force` - Clears existing wallet records. Warning! Use with caution!
|
||||
- `--batch-size <value>` - Number of filters that can be matched in one batch
|
||||
- `--start <value>` - Start height
|
||||
- `--end <value>` - End height
|
||||
- `--ignorecreationtime` - Ignores the wallet creation date and will instead do a full rescan
|
||||
- `isempty` - Checks if the wallet contains any data
|
||||
- `walletinfo` - Returns data about the current wallet being used
|
||||
- `getbalance` `[options]` - Get the wallet balance
|
||||
- `--sats ` - Display balance in satoshis
|
||||
- `getconfirmedbalance` `[options]` - Get the wallet balance of confirmed utxos
|
||||
- `--sats ` - Display balance in satoshis
|
||||
- `getunconfirmedbalance` `[options]` - Get the wallet balance of unconfirmed utxos
|
||||
- `--sats ` - Display balance in satoshis
|
||||
- `getbalances` `[options]` - Get the wallet balance by utxo state
|
||||
- `--sats ` - Display balance in satoshis
|
||||
- `getutxos` - Returns list of all wallet utxos
|
||||
- `getaddresses` - Returns list of all wallet addresses currently being watched
|
||||
- `getspentaddresses` - Returns list of all wallet addresses that have received funds and been spent
|
||||
- `getfundedaddresses` - Returns list of all wallet addresses that are holding funds
|
||||
- `getunusedaddresses` - Returns list of all wallet addresses that have not been used
|
||||
- `getaccounts` - Returns list of all wallet accounts
|
||||
- `walletinfo` - Returns meta information about the wallet
|
||||
- `createnewaccount` - Creates a new wallet account
|
||||
- `getaddressinfo` `address` - Returns list of all wallet accounts
|
||||
- `address` - Address to get information about
|
||||
- `getnewaddress` - Get a new address
|
||||
- `listreservedutxos` - lists all utxos that are reserved in the wallet
|
||||
- `sendtoaddress` `address` `amount` `[options]` - Send money to the given address
|
||||
- `address` - Address to send to
|
||||
- `amount` - Amount to send in BTC
|
||||
- `--feerate <value>` - Fee rate in sats per virtual byte
|
||||
- `sendfromoutpoints` `outpoints` `address` `amount` `[options]` - Send money to the given address
|
||||
- `outpoints` - Out Points to send from
|
||||
- `address` - Address to send to
|
||||
- `amount` - Amount to send in BTC
|
||||
- `--feerate <value>` - Fee rate in sats per virtual byte
|
||||
- `sweepwallet` `address` `[options]` - Sends the entire wallet balance to the given address
|
||||
- `address` - Address to send to
|
||||
- `--feerate <value>` - Fee rate in sats per virtual byte
|
||||
- `sendwithalgo` `address` `amount` `algo` `[options]` - Send money to the given address using a specific coin selection algo
|
||||
- `address` - Address to send to
|
||||
- `amount` - Amount to send in BTC
|
||||
- `algo` - Coin selection algo
|
||||
- `--feerate <value>` - Fee rate in sats per virtual byte
|
||||
- `signpsbt` `psbt` - Signs the PSBT's inputs with keys that are associated with the wallet
|
||||
- `psbt` - PSBT to sign
|
||||
- `opreturncommit` `message` `[options]` - Creates OP_RETURN commitment transaction
|
||||
- `message` - message to put into OP_RETURN commitment
|
||||
- `--hashMessage` - should the message be hashed before commitment
|
||||
- `--feerate <value>` - Fee rate in sats per virtual byte
|
||||
- `bumpfeecpfp` `txid` `feerate` - Bump the fee of the given transaction id with a child tx using the given fee rate
|
||||
- `txid` - Id of transaction to bump fee
|
||||
- `feerate` - Fee rate in sats per virtual byte of the child transaction
|
||||
- `bumpfeerbf` `txid` `feerate` - Replace given transaction with one with the new fee rate
|
||||
- `txid` - Id of transaction to bump fee
|
||||
- `feerate` - New fee rate in sats per virtual byte
|
||||
- `gettransaction` `txid` - Get detailed information about in-wallet transaction <txid>
|
||||
- `txid` - The transaction id
|
||||
- `lockunspent` `unlock` `transactions` - Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.
|
||||
- `unlock` - Whether to unlock (true) or lock (false) the specified transactions
|
||||
- `transactions` - The transaction outpoints to unlock/lock, empty to apply to all utxos
|
||||
- `importseed` `walletname` `words` `passphrase` - Imports a mnemonic seed as a new seed file
|
||||
- `walletname` - Name to associate with this seed
|
||||
- `words` - Mnemonic seed words, space separated
|
||||
- `passphrase` - Passphrase to encrypt this seed with
|
||||
- `importxprv` `walletname` `xprv` `passphrase` - Imports a mnemonic seed as a new seed file
|
||||
- `walletname` - Name to associate with this seed
|
||||
- `xprv` - base58 encoded extended private key
|
||||
- `passphrase` - Passphrase to encrypt this seed with
|
||||
- `keymanagerpassphrasechange` `oldpassphrase` `newpassphrase` - Changes the wallet passphrase
|
||||
- `oldpassphrase` - The current passphrase
|
||||
- `newpassphrase` - The new passphrase
|
||||
- `keymanagerpassphraseset` `passphrase` - Encrypts the wallet with the given passphrase
|
||||
- `passphrase` - The passphrase to encrypt the wallet with
|
||||
|
||||
### DLC
|
||||
- `createcontractinfo` `announcement` `totalCollateral` `payouts`
|
||||
- the announcement to build the contract info for
|
||||
- the total amount of collateral in the DLC
|
||||
- The payouts can be in two formats
|
||||
1. `{ "outcomes" : { "outcome0" : 0, "outcome1": 1, ... }}`. The number is the amount of sats paid to YOU for that outcome.
|
||||
2. `[{"outcome":0,"payout":0,"extraPrecision":0,"isEndpoint":true}, {"outcome":1,"payout":1,"extraPrecision":0,"isEndpoint":true}, ...]`
|
||||
- `decodecontractinfo` `contractinfo` - Decodes a contract info into json
|
||||
- `contractinfo` - Hex encoded contract info
|
||||
- `decodeoffer` `offer` - Decodes an offer message into json
|
||||
- `offer` - Hex encoded dlc offer message
|
||||
- `decodeaccept` `accept` - Decodes an accept message into json
|
||||
- `accept` - Hex encoded dlc accept message
|
||||
- `decodesign` `sign` - Decodes a sign message into json
|
||||
- `sign` - Hex encoded dlc sign message
|
||||
- `decodeannouncement` `announcement` - Decodes an oracle announcement message into json
|
||||
- `announcement` - Hex encoded oracle announcement message
|
||||
- `decodeattestments` `attestments` - Decodes an oracle attestments message into json
|
||||
- `attestments` - Hex encoded oracle attestments message
|
||||
- `getdlchostaddress` - Returns the public listening address of the DLC Node
|
||||
- `createdlcoffer` `contractInfo` `collateral` `[feerate]` `refundlocktime` `[options]` - Creates a DLC offer that another party can accept
|
||||
- `contractInfo` - Hex encoded contractInfo message
|
||||
- `collateral` - Satoshis to fund your side of the DLC
|
||||
- `feerate` - Fee rate for both funding and closing transactions, in sats/vbytes
|
||||
- `refundlocktime` - Locktime of the refund transaction
|
||||
- `cetlocktime <value>` - Should not be set unless you know what you are doing. Locktime of the contract execution transactions (defaults to current height)
|
||||
- `peer` - Peer's network address
|
||||
- `acceptdlc` `offer` `peer` - Accepts a DLC offer given from another party
|
||||
- `offer` - Hex encoded dlc offer message
|
||||
- `peer` - Peer's network address
|
||||
- `acceptdlcoffer` `offer` - Accepts a DLC offer given from another party
|
||||
- `offer` - Hex encoded offer message
|
||||
- `peer` - Peer's network address
|
||||
- `acceptdlcofferfromfile` `path` `[destination]` - Accepts a DLC offer given from another party
|
||||
- `path` - Path to dlc offer file
|
||||
- `destination` - Path to write dlc accept message
|
||||
- `contact-add` `alias` `address` `memo`
|
||||
- `alias` - alias for the address like a name
|
||||
- `address` - the tor address for the peer
|
||||
- `memo` - a memo for this contact
|
||||
- `contacts-list` - lists all contacts in the wallet
|
||||
- `contact-remove` `address`
|
||||
- `address` - the tor address for the peer to remove
|
||||
- `dlc-contact-add` `dlcid` `address` - Associated a DLC with a peer
|
||||
- `dlc-contact-remove` `dlcid` - Removes a DLC-peer association
|
||||
- `address` - the tor address for the peer to remove
|
||||
- `signdlc` `accept` - Signs a DLC
|
||||
- `accept` - Hex encoded dlc accept message
|
||||
- `signdlcfromfile` `path` `[destination]` - Signs a DLC
|
||||
- `path` - Path to dlc accept file
|
||||
- `destination` - Path to write dlc sign message
|
||||
- `adddlcsigs` `sigs` - Adds DLC Signatures into the database
|
||||
- `sigs` - Hex encoded dlc sign message
|
||||
- `adddlcsigsfromfile` `path` - Adds DLC Signatures into the database
|
||||
- `path` - Path to dlc sign file
|
||||
- `adddlcsigsandbroadcast` `sigs` - Adds DLC Signatures into the database and broadcasts the funding transaction
|
||||
- `sigs` - Hex encoded dlc sign message
|
||||
- `adddlcsigsandbroadcastfromfile` `path` - Adds DLC Signatures into the database and broadcasts the funding transaction
|
||||
- `path` - Path to dlc sign file
|
||||
- `getdlcfundingtx` `contractId` - Returns the Funding Tx corresponding to the DLC with the given contractId
|
||||
- `contractId` - ContractId of the DLC
|
||||
- `broadcastdlcfundingtx` `contractId` - Broadcasts the funding Tx corresponding to the DLC with the given contractId
|
||||
- `contractId` - ContractId of the DLC
|
||||
- `executedlc` `contractId` `oraclesigs` `[options]` - Executes the DLC with the given contractId
|
||||
- `contractId` - ContractId of the DLC
|
||||
- `oraclesigs` - Array of oracle attestations
|
||||
- `--noBroadcast` - Gives full serialized transaction instead of broadcasting
|
||||
- `executedlcrefund` `contractId` `[options]` - Executes the Refund transaction for the given DLC
|
||||
- `contractId` - ContractId of the DLC
|
||||
- `--noBroadcast` - Gives full serialized transaction instead of broadcasting
|
||||
- `canceldlc` `dlcId` - Cancels a DLC and unreserves used utxos
|
||||
- `dlcId` - Internal id of the DLC
|
||||
- `getdlcs` - Returns all dlcs in the wallet
|
||||
- `address` - optional contact address, if specified the RPC returns only DLCs associated with the given address
|
||||
- `getdlc` `dlcId` - Gets a specific dlc in the wallet
|
||||
- `dlcId` - Internal id of the DLC
|
||||
- `offer-add` `offerTLV` `peerAddress` `message` - Puts an incoming offer into the inbox
|
||||
- `offerTLV` - Offer TLV
|
||||
- `peer` - Peer URI (optional)
|
||||
- `message` - Peer's message or note (optional)
|
||||
- `"offer-remove` `hash` - Remove an incoming offer from inbox
|
||||
- `hash` - Hash of the offer TLV
|
||||
- `offer-send` `offerOrTempContractId` `peerAddress` `message` - Sends an offer to a peer. `offerOrTempContractId` is either an offer TLV or a temporary contract ID.
|
||||
- `offers-list` - List all incoming offers from the inbox
|
||||
- `getdlcoffer` `tempContractId` - Gets a DLC offer by temporary contract ID.
|
||||
- `getaddresslabel` `address` - gets all labels for an address
|
||||
- `getaddresslabels` - returns all addresses with labels in the wallet
|
||||
- `dropaddresslabel` `address` `label` - drops the label for a given address
|
||||
- `dropaddresslabels` `address` - drops all labels for the given address
|
||||
|
||||
### Network
|
||||
- `getpeers` - List the connected peers
|
||||
- `stop` - Request a graceful shutdown of Bitcoin-S
|
||||
- `sendrawtransaction` `tx` `Broadcasts the raw transaction`
|
||||
- `tx` - Transaction serialized in hex
|
||||
|
||||
### PSBT
|
||||
- `decodepsbt` `psbt` - Return a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.
|
||||
- `psbt` - PSBT serialized in hex or base64 format
|
||||
- `combinepsbts` `psbts` - Combines all the given PSBTs
|
||||
- `psbts` - PSBTs serialized in hex or base64 format
|
||||
- `joinpsbts` `psbts` - Combines all the given PSBTs
|
||||
- `psbts` - PSBTs serialized in hex or base64 format
|
||||
- `finalizepsbt` `psbt` - Finalizes the given PSBT if it can
|
||||
- `psbt` - PSBT serialized in hex or base64 format
|
||||
- `extractfrompsbt` `psbt` - Extracts a transaction from the given PSBT if it can
|
||||
- `psbt` - PSBT serialized in hex or base64 format
|
||||
- `converttopsbt` `unsignedTx` - Creates an empty psbt from the given transaction
|
||||
- `unsignedTx` - serialized unsigned transaction in hex
|
||||
|
||||
### Util
|
||||
- `createmultisig` `nrequired` `keys` `[address_type]` - Creates a multi-signature address with n signature of m keys required.
|
||||
- `nrequired` - The number of required signatures out of the n keys.
|
||||
- `keys` - The hex-encoded public keys.
|
||||
- `address_type` -The address type to use. Options are "legacy", "p2sh-segwit", and "bech32"
|
||||
- `estimatefee` - Returns the recommended fee rate using the fee provider
|
||||
|
||||
## Sign PSBT with Wallet Example
|
||||
|
||||
Bitcoin-S CLI:
|
||||
|
||||
```bash
|
||||
bitcoin-s-cli signpsbt cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA
|
||||
cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA
|
||||
```
|
||||
|
||||
CURL:
|
||||
```bash
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signpsbt", "params": ["cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA"]}' -H "Content-Type: application/json" http://127.0.0.1:9999/
|
||||
{"result":"cHNidP8BAP0FAQIAAAABWUWxYiPKgdGfXcIxJ6MRDxEpUecw59Gk4NpROI5oukoBAAAAAAAAAAAEPttkvdwAAAAXqRSOVAp6Qe/u2hq74e/ThB8foBKn7IfZYMgGCAAAAADbmaQ2nwAAAEdRIQLpfVqyaL9Jb/IkveatNyVeONE8Q/6TzXAWosxLo9e21SECc5G3XiK7xKLlkBG7prMx7p0fMeQwMH5e9H10mBon39JSrtgtgjjLAQAAUGMhAn2YaZnv25I6d6vbb1kw6Xp5IToDrEzl/0VBIW21gHrTZwXg5jGdALJ1IQKyNpDNiOiN6lWpYethib04+XC9bpFXrdpec+xO3U5IM2is9ckf5AABAD0CAAAAAALuiOL0rRcAABYAFPnpLByQq1Gg3vwiP6qR8FmOOjwxvVllM08DAAALBfXJH+QAsXUAAK4AAAAAAQcBAAAAAAAA","error":null}
|
||||
```
|
||||
|
||||
## Websocket endpoints
|
||||
|
||||
Bitcoin-s offers websocket endpoints. By default, the endpoint is `ws://localhost:1999/events`
|
||||
|
||||
You can configure where how the endpoints are configured inside your `bitcoin-s.conf`
|
||||
|
||||
```
|
||||
bitcoin-s.server.wsbind=localhost
|
||||
bitcoin-s.server.wsport=19999
|
||||
```
|
||||
|
||||
These events are implemented using our [internal callback mechanism](../wallet/wallet-callbacks.md#wallet-callbacks).
|
||||
|
||||
An example event that is defined is our `blockprocess` event.
|
||||
Everytime our wallet processes a block, our wallet will notify you via websockets.
|
||||
Here is an example payload
|
||||
|
||||
The current types of events defined are
|
||||
|
||||
1. `txprocessed` - when the wallet processes a transaction. Every transaction in a block will get relayed currently
|
||||
2. `reservedutxos` - when the wallet reserves OR unreserves utxos
|
||||
3. `newaddress` - when the wallet generates a new address
|
||||
4. `txbroadcast` - when the wallet broadcasts a tx
|
||||
5. `blockprocessed` - when the wallet processes a block
|
||||
```
|
||||
{"type":"blockprocessed","payload":{"raw":"04e0ff2ffce8c3e866e367d305886a3f9d353e557524f61f9cf0c26c46000000000000001206d2e396387bff1c13cbe572d4646abae1ae405f4066ab5e6f5edd6d8f028008a8bb61ffff001af23dd47e","hash":"00000000000000de21f23f6945f028d5ecb47863428f6e9e035ab2fb7a3ef356","confirmations":1,"height":2131641,"version":805298180,"versionHex":"2fffe004","merkleroot":"80028f6ddd5e6f5eab66405f40aee1ba6a64d472e5cb131cff7b3896e3d20612","time":1639688200,"mediantime":1639688200,"nonce":2127838706,"bits":"1a00ffff","difficulty":1.6069135243303364E60,"chainwork":"00000000000000000000000000000000000000000000062438437ddd009e698b","previousblockhash":"00000000000000466cc2f09c1ff62475553e359d3f6a8805d367e366e8c3e8fc","nextblockhash":null}}
|
||||
```
|
175
website/versioned_docs/version-1.9.2/chain/chain-query-api.md
Normal file
175
website/versioned_docs/version-1.9.2/chain/chain-query-api.md
Normal file
|
@ -0,0 +1,175 @@
|
|||
---
|
||||
id: version-1.9.2-chain-query-api
|
||||
title: Chain Query API
|
||||
original_id: chain-query-api
|
||||
---
|
||||
|
||||
|
||||
### ChainQueryAPI
|
||||
|
||||
The ChainQueryApi is how the wallet project stays aware of the current best chain.
|
||||
This allows the wallet for example to calculate the number of confirmations for a transaction,
|
||||
get the current chain tip, or even retrieve block filters for a given set of blocks.
|
||||
|
||||
Since this is an API it can be hooked up to the `chain` module of bitcoin-s but it can also be linked to
|
||||
any other implementation of your choosing. This allows you to use the bitcoin-s wallet in any schema that you
|
||||
want.
|
||||
|
||||
The functions that the ChainQueryApi supports are:
|
||||
|
||||
```scala
|
||||
trait ChainQueryApi {
|
||||
|
||||
/** Gets the height of the given block */
|
||||
def getBlockHeight(blockHash: DoubleSha256DigestBE): Future[Option[Int]]
|
||||
|
||||
/** Gets the hash of the block that is what we consider "best" */
|
||||
def getBestBlockHash(): Future[DoubleSha256DigestBE]
|
||||
|
||||
/** Gets number of confirmations for the given block hash*/
|
||||
def getNumberOfConfirmations(
|
||||
blockHashOpt: DoubleSha256DigestBE): Future[Option[Int]]
|
||||
|
||||
/** Gets the number of compact filters in the database */
|
||||
def getFilterCount: Future[Int]
|
||||
|
||||
/** Returns the block height of the given block stamp */
|
||||
def getHeightByBlockStamp(blockStamp: BlockStamp): Future[Int]
|
||||
|
||||
def getFiltersBetweenHeights(
|
||||
startHeight: Int,
|
||||
endHeight: Int): Future[Vector[FilterResponse]]
|
||||
|
||||
def getMedianTimePast(): Future[Long]
|
||||
}
|
||||
```
|
||||
|
||||
## Chain query with bitcoind
|
||||
|
||||
As an example, we will show you how to use the `ChainQueryApi` and bitcoind to query chain data.
|
||||
|
||||
```scala
|
||||
implicit val system: ActorSystem = ActorSystem(s"node-api-example")
|
||||
implicit val ec: ExecutionContextExecutor = system.dispatcher
|
||||
implicit val walletConf: WalletAppConfig =
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig().walletConf
|
||||
|
||||
// let's use a helper method to get a v19 bitcoind
|
||||
// and a ChainApi
|
||||
val instance = BitcoindInstanceLocal.fromConfigFile(BitcoindConfig.DEFAULT_CONF_FILE)
|
||||
val bitcoind = BitcoindV19RpcClient(instance)
|
||||
val nodeApi = BitcoinSWalletTest.MockNodeApi
|
||||
|
||||
// This function can be used to create a callback for when our chain api receives a transaction, block, or
|
||||
// a block filter, the returned NodeCallbacks will contain the necessary items to initialize the callbacks
|
||||
def createCallbacks(
|
||||
processTransaction: Transaction => Future[Unit],
|
||||
processCompactFilters: (Vector[(DoubleSha256Digest, GolombFilter)]) => Future[Unit],
|
||||
processBlock: Block => Future[Unit]): NodeCallbacks = {
|
||||
lazy val onTx: OnTxReceived = { tx =>
|
||||
processTransaction(tx)
|
||||
}
|
||||
lazy val onCompactFilters: OnCompactFiltersReceived = {
|
||||
blockFilters =>
|
||||
processCompactFilters(blockFilters)
|
||||
}
|
||||
lazy val onBlock: OnBlockReceived = { block =>
|
||||
processBlock(block)
|
||||
}
|
||||
NodeCallbacks(onTxReceived = Vector(onTx),
|
||||
onBlockReceived = Vector(onBlock),
|
||||
onCompactFiltersReceived = Vector(onCompactFilters))
|
||||
}
|
||||
|
||||
// Here is a super simple example of a callback, this could be replaced with anything, from
|
||||
// relaying the block on the network, finding relevant wallet transactions, verifying the block,
|
||||
// or writing it to disk
|
||||
val exampleProcessTx = (tx: Transaction) =>
|
||||
Future.successful(println(s"Received tx: ${tx.txIdBE}"))
|
||||
|
||||
val exampleProcessBlock = (block: Block) =>
|
||||
Future.successful(println(s"Received block: ${block.blockHeader.hashBE}"))
|
||||
|
||||
val exampleProcessFilters =
|
||||
(filters: Vector[(DoubleSha256Digest, GolombFilter)]) =>
|
||||
Future.successful(println(s"Received filter: ${filters.head._1.flip.hex} ${filters.head._2.hash.flip.hex}"))
|
||||
|
||||
val exampleCallbacks =
|
||||
createCallbacks(exampleProcessTx, exampleProcessFilters, exampleProcessBlock)
|
||||
|
||||
// Here is where we are defining our actual chain api, Ideally this could be it's own class
|
||||
// but for the examples sake we will keep it small.
|
||||
val chainApi = new ChainQueryApi {
|
||||
|
||||
override def epochSecondToBlockHeight(time: Long): Future[Int] =
|
||||
Future.successful(0)
|
||||
|
||||
/** Gets the height of the given block */
|
||||
override def getBlockHeight(
|
||||
blockHash: DoubleSha256DigestBE): Future[Option[Int]] = {
|
||||
bitcoind.getBlock(blockHash).map(block => Some(block.height))
|
||||
}
|
||||
|
||||
/** Gets the hash of the block that is what we consider "best" */
|
||||
override def getBestBlockHash(): Future[DoubleSha256DigestBE] = {
|
||||
bitcoind.getBestBlockHash
|
||||
}
|
||||
|
||||
/** Gets number of confirmations for the given block hash */
|
||||
override def getNumberOfConfirmations(
|
||||
blockHash: DoubleSha256DigestBE): Future[Option[Int]] = {
|
||||
for {
|
||||
tip <- bitcoind.getBlockCount
|
||||
block <- bitcoind.getBlock(blockHash)
|
||||
} yield {
|
||||
Some(tip - block.height + 1)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the number of compact filters in the database */
|
||||
override def getFilterCount(): Future[Int] = {
|
||||
// since bitcoind should have the filter for
|
||||
// every block we can just return the block height
|
||||
bitcoind.getBlockCount
|
||||
}
|
||||
|
||||
/** Returns the block height of the given block stamp */
|
||||
override def getHeightByBlockStamp(blockStamp: BlockStamp): Future[Int] = {
|
||||
blockStamp match {
|
||||
case blockHeight: BlockStamp.BlockHeight =>
|
||||
Future.successful(blockHeight.height)
|
||||
case blockHash: BlockStamp.BlockHash =>
|
||||
getBlockHeight(blockHash.hash).map(_.get)
|
||||
case blockTime: BlockStamp.BlockTime =>
|
||||
Future.failed(new RuntimeException(s"Not implemented: $blockTime"))
|
||||
}
|
||||
}
|
||||
|
||||
override def getFiltersBetweenHeights(
|
||||
startHeight: Int,
|
||||
endHeight: Int): Future[Vector[FilterResponse]] = {
|
||||
val filterFs = startHeight
|
||||
.until(endHeight)
|
||||
.map { height =>
|
||||
for {
|
||||
hash <- bitcoind.getBlockHash(height)
|
||||
filter <- bitcoind.getBlockFilter(hash, FilterType.Basic)
|
||||
} yield {
|
||||
FilterResponse(filter.filter, hash, height)
|
||||
}
|
||||
}
|
||||
.toVector
|
||||
|
||||
Future.sequence(filterFs)
|
||||
}
|
||||
|
||||
override def getMedianTimePast(): Future[Long] = bitcoind.getMedianTimePast()
|
||||
}
|
||||
|
||||
// Finally, we can initialize our wallet with our own node api
|
||||
val wallet =
|
||||
Wallet(nodeApi = nodeApi, chainQueryApi = chainApi, feeRateApi = ConstantFeeRateProvider(SatoshisPerVirtualByte.one))
|
||||
|
||||
// Then to trigger one of the events we can run
|
||||
wallet.chainQueryApi.getFiltersBetweenHeights(100, 150)
|
||||
```
|
59
website/versioned_docs/version-1.9.2/core/addresses.md
Normal file
59
website/versioned_docs/version-1.9.2/core/addresses.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
id: version-1.9.2-addresses
|
||||
title: Generating Addresses
|
||||
original_id: addresses
|
||||
---
|
||||
|
||||
Almost all Bitcoin applications need to generate addresses
|
||||
for their users somehow. There's a lot going on in getting
|
||||
a correct bitcoin address, but our APIs make it possible to
|
||||
to get started with all types of addresses in a matter of
|
||||
minutes.
|
||||
|
||||
## Generating SegWit (bech32) addresses
|
||||
|
||||
Generating native SegWit addresses in the bech32 format
|
||||
is something that all Bitcoin applications should enable,
|
||||
as it makes the transaction fees less expensive, and also
|
||||
makes the addresses more readable by humans. However, it
|
||||
has seen slower than necessary adoption. With Bitcoin-S
|
||||
you can generate bech32 addresses in four(!) lines of code
|
||||
(not counting comments and imports), so now there's no
|
||||
reason to keep using legacy transaction formats.
|
||||
|
||||
|
||||
```scala
|
||||
// this generates a random private key
|
||||
val privkey = ECPrivateKey()
|
||||
// privkey: ECPrivateKey = Masked(ECPrivateKey)
|
||||
val pubkey = privkey.publicKey
|
||||
// pubkey: org.bitcoins.crypto.ECPublicKey = ECPublicKey(0399dea3a0dad9e21812f94ad69262a94fd51a2ed2b1507928afce2a358907a2de)
|
||||
|
||||
val segwitAddress = {
|
||||
// see https://bitcoin.org/en/glossary/pubkey-script
|
||||
// for reading resources on the details of scriptPubKeys
|
||||
// pay-to-witness-pubkey-hash scriptPubKey V0
|
||||
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
|
||||
Bech32Address(scriptPubKey, TestNet3)
|
||||
}
|
||||
// segwitAddress: Bech32Address = tb1qd5kg59zdpa7xqm3qnqwnuj7sxwzvx6axy8ncja
|
||||
|
||||
println(segwitAddress.toString)
|
||||
// tb1qd5kg59zdpa7xqm3qnqwnuj7sxwzvx6axy8ncja
|
||||
```
|
||||
|
||||
## Generating legacy (base58) addresses
|
||||
|
||||
If you need to generate legacy addresses for backwards
|
||||
compatability reasons, that's also a walk in the park.
|
||||
Take a look:
|
||||
|
||||
```scala
|
||||
// we're reusing the same private/public key pair
|
||||
// from before. don't do this in an actual application!
|
||||
val legacyAddress = P2PKHAddress(pubkey, TestNet3)
|
||||
// legacyAddress: P2PKHAddress = mqUDJcXeTYj9R2eU4ksu57UhNFtzAbeaYS
|
||||
|
||||
println(legacyAddress.toString)
|
||||
// mqUDJcXeTYj9R2eU4ksu57UhNFtzAbeaYS
|
||||
```
|
225
website/versioned_docs/version-1.9.2/core/dlc.md
Normal file
225
website/versioned_docs/version-1.9.2/core/dlc.md
Normal file
File diff suppressed because one or more lines are too long
145
website/versioned_docs/version-1.9.2/core/hd-keys.md
Normal file
145
website/versioned_docs/version-1.9.2/core/hd-keys.md
Normal file
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
id: version-1.9.2-hd-keys
|
||||
title: HD Key Generation
|
||||
original_id: hd-keys
|
||||
---
|
||||
|
||||
In modern Bitcoin wallets, users only need to write down
|
||||
a sequence of words, and that sequence is a complete backup
|
||||
of their wallet. This is thanks to what's called Hierarchical
|
||||
Deterministic key generation. In short, every wallet using HD
|
||||
key generation has a root seed for each wallet, and this
|
||||
seed can be used to generate an arbitrary amount of later
|
||||
private and public keys. This is done in a standardized manner,
|
||||
so different wallets can operate with the same standard.
|
||||
|
||||
> If you want to jump into the details of how this work,
|
||||
> you should check out
|
||||
> [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).
|
||||
|
||||
Bitcoin-S supports generating keys in this fashion. Here's a
|
||||
full example of how to obtain a wallet seed, and then
|
||||
use that to generate further private and public keys:
|
||||
|
||||
```scala
|
||||
import scodec.bits._
|
||||
import org.bitcoins.core.crypto._
|
||||
import org.bitcoins.core.hd._
|
||||
|
||||
// the length of the entropy bit vector determine
|
||||
// how long our phrase ends up being
|
||||
// 256 bits of entropy results in 24 words
|
||||
val entropy: BitVector = MnemonicCode.getEntropy256Bits
|
||||
// entropy: BitVector = BitVector(256 bits, 0x2c3bfad990775c8e1f1c0be259d97a5c06965922f1a5e2502dbbdb4dd1da574d)
|
||||
|
||||
val mnemonicCode = MnemonicCode.fromEntropy(entropy)
|
||||
// mnemonicCode: MnemonicCode = Masked(MnemonicCodeImpl)
|
||||
|
||||
mnemonicCode.words // the phrase the user should write down
|
||||
// res0: Vector[String] = Vector(club, thank, reopen, can, into, either, ladder, lift, time, solution, future, retreat, harvest, clutch, mesh, cruise, time, lift, humble, repair, tackle, unfold, frog, pave) // the phrase the user should write down
|
||||
|
||||
// the password argument is an optional, extra security
|
||||
// measure. all MnemonicCode instances will give you a
|
||||
// valid BIP39 seed, but different passwords will give
|
||||
// you different seeds. So you could have as many wallets
|
||||
// from the same seed as you'd like, by simply giving them
|
||||
// different passwords.
|
||||
val bip39Seed = BIP39Seed.fromMnemonic(mnemonicCode,
|
||||
password = "secret password")
|
||||
// bip39Seed: BIP39Seed = Masked(BIP39SeedImpl)
|
||||
|
||||
val xpriv = ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.SegWitMainNetPriv,
|
||||
bip39Seed)
|
||||
// xpriv: ExtPrivateKey = Masked(ExtPrivateKeyImpl)
|
||||
val xpub = xpriv.extPublicKey
|
||||
// xpub: ExtPublicKey = zpub6jftahH18ngZwEWTZuNHbNgJ39b2sdz5sMXKRv5pXbugPn2b4frQfi7P97CwqRRYmL6PmAC1erwFRMJf66oE64vdmkR3QW4bsxrotEoGKkh
|
||||
|
||||
// you can now use the generated xpriv to derive further
|
||||
// private or public keys
|
||||
|
||||
// this can be done with BIP89 paths (called SegWitHDPath in bitcoin-s)
|
||||
val segwitPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
|
||||
// segwitPath: SegWitHDPath = m/84'/0'/0'/0/0
|
||||
|
||||
// alternatively:
|
||||
val otherSegwitPath =
|
||||
SegWitHDPath(HDCoinType.Bitcoin,
|
||||
accountIndex = 0,
|
||||
HDChainType.External,
|
||||
addressIndex = 0)
|
||||
// otherSegwitPath: SegWitHDPath = m/84'/0'/0'/0/0
|
||||
|
||||
segwitPath == otherSegwitPath
|
||||
// res1: Boolean = true
|
||||
```
|
||||
|
||||
## Generating new addresses without having access to the private key
|
||||
|
||||
One the coolest features of HD wallets is that it's possible
|
||||
to generate addresses offline, without having access to the
|
||||
private keys. This feature is commonly called watch-only
|
||||
wallets, where a wallet can import information about all
|
||||
your past and future transactions, without being able to
|
||||
spend or steal any of your money.
|
||||
|
||||
Let's see an example of this:
|
||||
|
||||
```scala
|
||||
import scala.util.Success
|
||||
import org.bitcoins.core.protocol.script._
|
||||
import org.bitcoins.core.protocol.Bech32Address
|
||||
import org.bitcoins.core.config.TestNet3
|
||||
|
||||
// first account -------┐
|
||||
// bitcoin ----------┐ |
|
||||
// segwit --------┐ | |
|
||||
val accountPath = BIP32Path.fromString("m/84'/0'/0'")
|
||||
// accountPath: BIP32Path = m/84'/0'/0'
|
||||
val accountXpub = {
|
||||
// this key is sensitive, keep away from prying eyes!
|
||||
val accountXpriv = xpriv.deriveChildPrivKey(accountPath)
|
||||
|
||||
// this key is not sufficient to spend from, but we
|
||||
// can generate addresses with it!
|
||||
accountXpriv.extPublicKey
|
||||
}
|
||||
// accountXpub: ExtPublicKey = zpub6qnQJzSgN1NaJp5kPY7DPbc3joQ7Fw6vkdTCBtwKdsBTxpLECH84qv85LnsPLq3eVKnopY1b4PNBADWCmQs4SxvPbm7iwvkafk2miN8vGhx
|
||||
|
||||
// address no. 0 ---------------┐
|
||||
// external address ----------┐ |
|
||||
val firstAddressPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
|
||||
// firstAddressPath: SegWitHDPath = m/84'/0'/0'/0/0
|
||||
val firstAccountAddress = {
|
||||
// this is a bit quirky, but we're not interesting in
|
||||
// deriving the complete path from our account xpub
|
||||
// instead, we're only interested in the part after
|
||||
// the account level (3rd level). the .diff() method
|
||||
// achieves that
|
||||
val Some(pathDiff) = accountPath.diff(firstAddressPath)
|
||||
|
||||
// deriving public keys from hardened extended keys
|
||||
// is not possible, that's why .deriveChildPubKey()
|
||||
// returns a Try[ExtPublicKey]. A hardened key is marked
|
||||
// by a ' after the number in the notation we use above.
|
||||
val Success(extPubKey) = accountXpub.deriveChildPubKey(pathDiff)
|
||||
val pubkey = extPubKey.key
|
||||
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
|
||||
Bech32Address(scriptPubKey, TestNet3)
|
||||
}
|
||||
// firstAccountAddress: Bech32Address = tb1qv32jwzqxyfqz6mss4z9kvq6pnye0chvqpm3a24
|
||||
|
||||
// tada! We just generated an address you can send money to,
|
||||
// without having access to the private key!
|
||||
firstAccountAddress.value
|
||||
// res2: String = tb1qv32jwzqxyfqz6mss4z9kvq6pnye0chvqpm3a24
|
||||
|
||||
// you can now continue deriving addresses from the same public
|
||||
// key, by imitating what we did above. To get the next
|
||||
// HD path to generate an address at:
|
||||
val nextAddressPath: SegWitHDPath = firstAddressPath.next
|
||||
// nextAddressPath: SegWitHDPath = m/84'/0'/0'/0/1
|
||||
```
|
||||
|
||||
### Signing things with HD keys
|
||||
|
||||
Please see [sign.md](../crypto/sign.md) for information on how to sign things with HD keys.
|
158
website/versioned_docs/version-1.9.2/core/txbuilder.md
Normal file
158
website/versioned_docs/version-1.9.2/core/txbuilder.md
Normal file
|
@ -0,0 +1,158 @@
|
|||
---
|
||||
id: version-1.9.2-txbuilder
|
||||
title: TxBuilder Example
|
||||
original_id: txbuilder
|
||||
---
|
||||
|
||||
Bitcoin-S features a transaction building API that allows you to construct and sign Bitcoin transactions. Here's an example of how to use it
|
||||
|
||||
|
||||
```scala
|
||||
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
|
||||
// ec: ExecutionContext = scala.concurrent.impl.ExecutionContextImpl$$anon$3@7081ff47[Running, parallelism = 16, size = 0, active = 0, running = 0, steals = 0, tasks = 0, submissions = 0]
|
||||
|
||||
// Initialize a transaction builder
|
||||
val builder = RawTxBuilder()
|
||||
// builder: RawTxBuilder = RawTxBuilder()
|
||||
|
||||
// generate a fresh private key that we are going to use in the scriptpubkey
|
||||
val privKey = ECPrivateKey.freshPrivateKey
|
||||
// privKey: ECPrivateKey = Masked(ECPrivateKey)
|
||||
val pubKey = privKey.publicKey
|
||||
// pubKey: ECPublicKey = ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)
|
||||
|
||||
// this is the script that the TxBuilder is going to create a
|
||||
// script signature that validly spends this scriptPubKey
|
||||
val creditingSpk = P2PKHScriptPubKey(pubKey = privKey.publicKey)
|
||||
// creditingSpk: P2PKHScriptPubKey = pkh(7484de8aafb35f3f70b2d50128055867e1f746ec)
|
||||
val amount = 10000.satoshis
|
||||
// amount: Satoshis = 10000 sats
|
||||
|
||||
// this is the UTXO we are going to be spending
|
||||
val utxo =
|
||||
TransactionOutput(value = amount, scriptPubKey = creditingSpk)
|
||||
// utxo: TransactionOutput = TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))
|
||||
|
||||
// the private key that locks the funds for the script we are spending too
|
||||
val destinationPrivKey = ECPrivateKey.freshPrivateKey
|
||||
// destinationPrivKey: ECPrivateKey = Masked(ECPrivateKey)
|
||||
|
||||
// the amount we are sending -- 5000 satoshis -- to the destinationSPK
|
||||
val destinationAmount = 5000.satoshis
|
||||
// destinationAmount: Satoshis = 5000 sats
|
||||
|
||||
// the script that corresponds to destination private key, this is what is receiving the money
|
||||
val destinationSPK =
|
||||
P2PKHScriptPubKey(pubKey = destinationPrivKey.publicKey)
|
||||
// destinationSPK: P2PKHScriptPubKey = pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)
|
||||
|
||||
// this is where we are sending money too
|
||||
// we could add more destinations here if we
|
||||
// wanted to batch transactions
|
||||
val destinations = {
|
||||
val destination0 = TransactionOutput(value = destinationAmount,
|
||||
scriptPubKey = destinationSPK)
|
||||
|
||||
Vector(destination0)
|
||||
}
|
||||
// destinations: Vector[TransactionOutput] = Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)))
|
||||
|
||||
// Add the destinations to the tx builder
|
||||
builder ++= destinations
|
||||
// res0: RawTxBuilder = RawTxBuilder()
|
||||
|
||||
// we have to fabricate a transaction that contains the
|
||||
// UTXO we are trying to spend. If this were a real blockchain
|
||||
// we would need to reference the UTXO set
|
||||
val creditingTx = BaseTransaction(version = Int32.one,
|
||||
inputs = Vector.empty,
|
||||
outputs = Vector(utxo),
|
||||
lockTime = UInt32.zero)
|
||||
// creditingTx: BaseTransaction = BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))),UInt32Impl(0))
|
||||
|
||||
// this is the information we need from the crediting TX
|
||||
// to properly "link" it in the transaction we are creating
|
||||
val outPoint = TransactionOutPoint(creditingTx.txId, UInt32.zero)
|
||||
// outPoint: TransactionOutPoint = TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0)
|
||||
val input = TransactionInput(
|
||||
outPoint,
|
||||
EmptyScriptSignature,
|
||||
sequenceNumber = UInt32.zero)
|
||||
// input: TransactionInput = TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),EmptyScriptSignature,UInt32Impl(0))
|
||||
|
||||
// Add a new input to our builder
|
||||
builder += input
|
||||
// res1: RawTxBuilder = RawTxBuilder()
|
||||
|
||||
// We can now generate a RawTxBuilderResult ready to be finalized
|
||||
val builderResult = builder.result()
|
||||
// builderResult: RawTxBuilderResult = RawTxBuilderResult(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d))),UInt32Impl(0))
|
||||
|
||||
// this contains the information needed to analyze our input during finalization
|
||||
val inputInfo = P2PKHInputInfo(outPoint, amount, privKey.publicKey)
|
||||
// inputInfo: P2PKHInputInfo = P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66))
|
||||
|
||||
// this is how much we are going to pay as a fee to the network
|
||||
// for this example, we are going to pay 1 satoshi per byte
|
||||
val feeRate = SatoshisPerByte(1.satoshi)
|
||||
// feeRate: SatoshisPerByte = 1 sats/byte
|
||||
|
||||
val changePrivKey = ECPrivateKey.freshPrivateKey
|
||||
// changePrivKey: ECPrivateKey = Masked(ECPrivateKey)
|
||||
val changeSPK = P2PKHScriptPubKey(pubKey = changePrivKey.publicKey)
|
||||
// changeSPK: P2PKHScriptPubKey = pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb)
|
||||
|
||||
// We chose a finalizer that adds a change output to our tx based on a fee rate
|
||||
val finalizer = StandardNonInteractiveFinalizer(
|
||||
Vector(inputInfo),
|
||||
feeRate,
|
||||
changeSPK)
|
||||
// finalizer: StandardNonInteractiveFinalizer = StandardNonInteractiveFinalizer(Vector(P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66))),1 sats/byte,pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb))
|
||||
|
||||
// We can now finalize the tx builder result from earlier with this finalizer
|
||||
val unsignedTx: Transaction = finalizer.buildTx(builderResult)
|
||||
// unsignedTx: Transaction = BaseTransaction(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)), TransactionOutput(4775 sats,pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb))),UInt32Impl(0))
|
||||
|
||||
// We now turn to signing the unsigned transaction
|
||||
// this contains all the information we need to
|
||||
// validly sign the UTXO above
|
||||
val utxoInfo = ScriptSignatureParams(inputInfo = inputInfo,
|
||||
prevTransaction = creditingTx,
|
||||
signers = Vector(privKey),
|
||||
hashType =
|
||||
HashType.sigHashAll)
|
||||
// utxoInfo: ScriptSignatureParams[P2PKHInputInfo] = ScriptSignatureParams(P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(1))
|
||||
|
||||
// all of the UTXO spending information, since we only have
|
||||
// one input, this is just one element
|
||||
val utxoInfos: Vector[ScriptSignatureParams[InputInfo]] = Vector(utxoInfo)
|
||||
// utxoInfos: Vector[ScriptSignatureParams[InputInfo]] = Vector(ScriptSignatureParams(P2PKHInputInfo(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),10000 sats,ECPublicKey(02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(7484de8aafb35f3f70b2d50128055867e1f746ec))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(1)))
|
||||
|
||||
// Yay! Now we use the RawTxSigner object to sign the tx.
|
||||
// The 'sign' method is going produce a validly signed transaction
|
||||
// This is going to iterate through each of the UTXOs and use
|
||||
// the corresponding ScriptSignatureParams to produce a validly
|
||||
// signed input. This UTXO has:
|
||||
// 1: one input
|
||||
// 2: outputs (destination and change outputs)
|
||||
// 3: a fee rate of 1 satoshi/byte
|
||||
val signedTx: Transaction =
|
||||
RawTxSigner.sign(
|
||||
utx = unsignedTx,
|
||||
utxoInfos = utxoInfos,
|
||||
expectedFeeRate = feeRate
|
||||
)
|
||||
// signedTx: Transaction = BaseTransaction(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(7dc3325732ab173e107b4e78c0dd64c901446feeb1962d8ef9d71c475464cd58:0),P2PKHScriptSignature(ECPublicKeyBytes(ByteVector(33 bytes, 0x02115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66)), ECDigitalSignature(30440220627fc2103f7be50d464c9d331e3279251ee906436c91afb8ba8cb8ac82f7306002203edfa71859c4d8d3d8f8105ff6df5b4cc7a2b4d6c73cf3a55877b4f7f9b97ebd01)),UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(80d74f124249a58880a7998bc10f99eb80b0f98d)), TransactionOutput(4775 sats,pkh(521c5467aef9b4c106840ef901fcd0fa7487d7bb))),UInt32Impl(0))
|
||||
```
|
||||
|
||||
```scala
|
||||
signedTx.inputs.length
|
||||
// res2: Int = 1
|
||||
|
||||
signedTx.outputs.length
|
||||
// res3: Int = 2
|
||||
|
||||
//remember, you can call .hex on any bitcoin-s data structure to get the hex representation!
|
||||
signedTx.hex
|
||||
// res4: String = 020000000158cd6454471cd7f98e2d96b1ee6f4401c964ddc0784e7b103e17ab325732c37d000000006a4730440220627fc2103f7be50d464c9d331e3279251ee906436c91afb8ba8cb8ac82f7306002203edfa71859c4d8d3d8f8105ff6df5b4cc7a2b4d6c73cf3a55877b4f7f9b97ebd012102115643538b661ced861a8424c89a8a5fd2f8aa3bcddc36a89e031af05ee53b66000000000288130000000000001976a91480d74f124249a58880a7998bc10f99eb80b0f98d88aca7120000000000001976a914521c5467aef9b4c106840ef901fcd0fa7487d7bb88ac00000000
|
||||
```
|
65
website/versioned_docs/version-1.9.2/crypto/sign.md
Normal file
65
website/versioned_docs/version-1.9.2/crypto/sign.md
Normal file
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
id: version-1.9.2-sign
|
||||
title: Sign API
|
||||
original_id: sign
|
||||
---
|
||||
|
||||
### The [`Sign` API](/api/org/bitcoins/crypto/Sign)
|
||||
|
||||
This is the API we define to sign things with. It takes in an arbitrary byte vector and returns a `Future[ECDigitalSignature]`. The reason we incorporate `Future`s here is for extensibility of this API. We would like to provide implementations of this API for hardware devices, which need to be asynchrnous since they may require user input.
|
||||
|
||||
From [Sign.scala](/api/org/bitcoins/crypto/Sign):
|
||||
|
||||
```scala
|
||||
import scodec.bits._
|
||||
import org.bitcoins.crypto._
|
||||
import scala.concurrent._
|
||||
import scala.concurrent.duration._
|
||||
|
||||
trait Sign {
|
||||
def signFunction: ByteVector => Future[ECDigitalSignature]
|
||||
|
||||
def signFuture(bytes: ByteVector): Future[ECDigitalSignature] =
|
||||
signFunction(bytes)
|
||||
|
||||
def sign(bytes: ByteVector): ECDigitalSignature = {
|
||||
Await.result(signFuture(bytes), 30.seconds)
|
||||
}
|
||||
|
||||
def publicKey: ECPublicKey
|
||||
}
|
||||
```
|
||||
|
||||
The `ByteVector` that is input to the `signFunction` should be the hash that is output from [`TransactionSignatureSerializer`](/api/org/bitcoins/core/crypto/TransactionSignatureSerializer)'s `hashForSignature` method. Our in-memory [`BaseECKey`](/api/org/bitcoins/crypto/BaseECKey) types implement the `Sign` API.
|
||||
|
||||
If you wanted to implement a new `Sign` api for a hardware wallet, you can easily pass it into the `TxBuilder`/`Signer` classes to allow for you to use those devices to sign with Bitcoin-S.
|
||||
|
||||
This API is currently used to sign ordinary transactions with our [`Signer`](/api/org/bitcoins/core/wallet/signer/Signer)s. The `Signer` subtypes (i.e. `P2PKHSigner`) implement the specific functionality needed to produce a valid digital signature for their corresponding script type.
|
||||
|
||||
|
||||
### The [`ExtSign`](/api/org/bitcoins/crypto/Sign) API.
|
||||
|
||||
An [ExtKey](/api/org/bitcoins/core/crypto/ExtKey) is a data structure that can be used to generate more keys from a parent key. For more information look at [hd-keys.md](../core/hd-keys.md)
|
||||
|
||||
You can sign with `ExtPrivateKey` the same way you could with a normal `ECPrivateKey`.
|
||||
|
||||
```scala
|
||||
import org.bitcoins.core.hd._
|
||||
import org.bitcoins.core.crypto._
|
||||
|
||||
val extPrivKey = ExtPrivateKey(ExtKeyVersion.SegWitMainNetPriv)
|
||||
// extPrivKey: ExtPrivateKey = Masked(ExtPrivateKeyImpl)
|
||||
|
||||
extPrivKey.sign(DoubleSha256Digest.empty.bytes)
|
||||
// res0: ECDigitalSignature = ECDigitalSignature(3045022100ad428f1b54cfb39e85f68fe1f22f859ed956da162d4279b70b96a1a5b24ec182022000cd632d703dadea9186621550a923df1edf808352f22dab0f41f031c694e0c1)
|
||||
|
||||
val path = BIP32Path(Vector(BIP32Node(0,false)))
|
||||
// path: BIP32Path = m/0
|
||||
|
||||
extPrivKey.sign(DoubleSha256Digest.empty.bytes,path)
|
||||
// res1: ECDigitalSignature = ECDigitalSignature(3044022054b0e675629d0ceb6e5aac6171244f516918bf5967aa741deab9bb745bed750e0220333bfbb14108ce3a87a17bd52ec6dae22a24a6bc4fb9efb3d75c112297babfc0)
|
||||
```
|
||||
|
||||
With `ExtSign`, you can use `ExtPrivateKey` to sign transactions inside of `TxBuilder` since `UTXOSpendingInfo` takes in `Sign` as a parameter.
|
||||
|
||||
You can also provide a `path` to use to derive a child `ExtPrivateKey`, and then sign with that child private key
|
127
website/versioned_docs/version-1.9.2/getting-started.md
Normal file
127
website/versioned_docs/version-1.9.2/getting-started.md
Normal file
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
id: version-1.9.2-getting-started
|
||||
title: Intro and Getting Started
|
||||
original_id: getting-started
|
||||
---
|
||||
|
||||
## Philosophy
|
||||
|
||||
Bitcoin-S is a loosely coupled set of cryptocurrency libraries for the JVM. They work well together, but also can be used
|
||||
independently. This project's goal is NOT to be a full node implementation, rather a set of scalable cryptocurrency libraries
|
||||
that use industry standard tools (rather than esoteric tech often found in cryptocurrency) where possible to make the lives of professional
|
||||
software engineers, security engineers, devops engineers and accountants easier.
|
||||
We are rapidly iterating on development with the goal of getting to a set of stable APIs that only change when the underlying bitcoin protocol changes.
|
||||
|
||||
If you are a professional working a cryptocurrency business and
|
||||
have feedback on how to make your lives easier, please reach out on [slack](https://join.slack.com/t/suredbits/shared_invite/zt-eavycu0x-WQL7XOakzQo8tAy7jHHZUw),
|
||||
[gitter](https://gitter.im/bitcoin-s-core/) or [twitter](https://twitter.com/Chris_Stewart_5/)!
|
||||
|
||||
## Getting prebuilt artifacts
|
||||
|
||||
### Java binaries
|
||||
|
||||
<details>
|
||||
|
||||
#### Latest release
|
||||
|
||||
Please see the release page on github, you can find it [here](https://github.com/bitcoin-s/bitcoin-s/releases)
|
||||
|
||||
#### Master builds
|
||||
|
||||
We build installers for mac, linux and windows everytime a PR is merged to master.
|
||||
|
||||
You can find the latest builds at this link:
|
||||
|
||||
https://github.com/bitcoin-s/bitcoin-s/actions/workflows/release.yml
|
||||
|
||||
Here is what the installers look like
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
### Docker
|
||||
|
||||
<details>
|
||||
We publish docker images to docker hub on every PR merge and tag on github.
|
||||
You can obtain the images for both the app server and oracle server on these
|
||||
docker hub repos
|
||||
|
||||
[bitcoin-s-server docker hub repo](https://hub.docker.com/r/bitcoinscala/bitcoin-s-server/tags?page=1&ordering=last_updated)
|
||||
|
||||
[bitcoin-s-oracle-server docker hub repo](https://hub.docker.com/r/bitcoinscala/bitcoin-s-oracle-server/tags?page=1&ordering=last_updated)
|
||||
</details>
|
||||
|
||||
### Library jars
|
||||
|
||||
<details>
|
||||
Add this to your `build.sbt`:
|
||||
|
||||
```scala
|
||||
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-bitcoind-rpc" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-core" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-chain" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-oracle" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-eclair-rpc" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-fee-provider" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-key-manager" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-lnd-rpc" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-node" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-oracle-explorer-client" % "1.9.1"
|
||||
|
||||
libraryDependencies +="org.bitcoin-s" % "bitcoin-s-secp256k1jni" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit-core" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-wallet" % "1.9.1"
|
||||
|
||||
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-zmq" % "1.9.1"
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Nightly builds
|
||||
|
||||
You can also run on the bleeding edge of Bitcoin-S, by
|
||||
adding a snapshot build to your `build.sbt`. The most
|
||||
recent snapshot published is `1.9.1-91-1ad54070-SNAPSHOT`.
|
||||
|
||||
|
||||
|
||||
To fetch snapshots, you will need to add the correct
|
||||
resolver in your `build.sbt`:
|
||||
|
||||
```sbt
|
||||
resolvers += Resolver.sonatypeRepo("snapshots")
|
||||
```
|
||||
|
||||
The official maven repo for releases is
|
||||
|
||||
https://repo1.maven.org/maven2/org/bitcoin-s/
|
||||
|
||||
The repo for snapshots, which are published after everytime something is merged to master:
|
||||
|
||||
https://oss.sonatype.org/content/repositories/snapshots/org/bitcoin-s/
|
||||
|
||||
</details>
|
||||
|
||||
## Building JARs yourself
|
||||
|
||||
Please see [our setup docs](getting-setup.md)
|
||||
|
||||
## If you want to setup Bitcoin-S locally for development
|
||||
|
||||
Please see [our setup docs](getting-setup.md)
|
124
website/versioned_docs/version-1.9.2/key-manager/key-manager.md
Normal file
124
website/versioned_docs/version-1.9.2/key-manager/key-manager.md
Normal file
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
id: version-1.9.2-key-manager
|
||||
title: Key Manager
|
||||
original_id: key-manager
|
||||
---
|
||||
|
||||
|
||||
### Key Manager
|
||||
|
||||
The key manager module's goal is to encapsulate all private key interactions with the [wallet](../wallet/wallet.md) project.
|
||||
|
||||
As of this writing, there is only one type of `KeyManager` - [`BIP39KeyManager`](/api/org/bitcoins/keymanager/bip39/BIP39KeyManager).
|
||||
|
||||
The [`BIP39KeyManager`](/api/org/bitcoins/keymanager/bip39/BIP39KeyManager) stores a [`MnemonicCode`](/api/org/bitcoins/core/crypto/MnemonicCode) on disk which can be decrypted and used as a hot wallet.
|
||||
|
||||
Over the long run, we want to make it so that the wallet project needs to communicate with the key-manager to access private keys.
|
||||
|
||||
This means that ALL SIGNING should be done inside of the key-manager, and private keys should not leave the key manager.
|
||||
|
||||
This makes it easier to reason about the security characteristics of our private keys, and a way to provide a uniform interface for alternative key storage systems (hsm, cloud based key storage, etc) to be plugged into the bitcoin-s library.
|
||||
|
||||
#### Creating a key manager
|
||||
|
||||
The first thing you need create a key manager is some entropy.
|
||||
|
||||
A popular way for bitcoin wallet's to represent entropy is [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) which you [can use in bitcoin-s](/api/org/bitcoins/core/crypto/BIP39Seed)
|
||||
|
||||
You can generate a `MnemonicCode` in bitcoin-s with the following code
|
||||
|
||||
```scala
|
||||
import org.bitcoins.core.crypto._
|
||||
|
||||
//get 256 bits of random entropy
|
||||
val entropy = MnemonicCode.getEntropy256Bits
|
||||
// entropy: scodec.bits.BitVector = BitVector(256 bits, 0x3eb8d4d6450a76d79e3a007adc3d3493d9efd684b0ede33262bf28118a13ac4d)
|
||||
|
||||
val mnemonic = MnemonicCode.fromEntropy(entropy)
|
||||
// mnemonic: MnemonicCode = Masked(MnemonicCodeImpl)
|
||||
|
||||
//you can print that mnemonic seed with this
|
||||
println(mnemonic.words)
|
||||
// Vector(dirt, shop, culture, meat, polar, hint, jump, divorce, kiss, tiger, essay, chicken, page, twice, barrel, buffalo, tobacco, narrow, quit, expand, board, antenna, raise, real)
|
||||
```
|
||||
|
||||
Now that we have a `MnemonicCode` that was securely generated, we need to now create `KeyManagerParams` which tells us how to generate
|
||||
generate specific kinds of addresses for wallets.
|
||||
|
||||
`KeyManagerParams` takes 3 parameters:
|
||||
|
||||
1. `seedPath` there is where we store the `MnemonicCode` on your file system
|
||||
2. [`purpose`](/api/org/bitcoins/core/hd/HDPurpose) which represents what type of utxo this `KeyManager` is associated with. The specification for this is in [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)
|
||||
3. [`network`](/api/org/bitcoins/core/config/NetworkParameters) what cryptocurrency network this key manager is associated with
|
||||
|
||||
|
||||
This controls how the root key is defined. The combination of `purpose` and `network` determine how the root `ExtKey` is serialized. For more information on how this works please see [hd-keys](../core/hd-keys.md)
|
||||
|
||||
Now we can construct a native segwit key manager for the regtest network!
|
||||
|
||||
```scala
|
||||
//this will create a temp directory with the prefix 'key-manager-example` that will
|
||||
//have a file in it called "encrypted-bitcoin-s-seed.json"
|
||||
val seedPath = Files.createTempDirectory("key-manager-example").resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
|
||||
// seedPath: Path = /tmp/key-manager-example4040417810562189104/encrypted-bitcoin-s-seed.json
|
||||
|
||||
//let's create a native segwit key manager
|
||||
val purpose = HDPurposes.SegWit
|
||||
// purpose: HDPurpose = m/84'
|
||||
|
||||
//let's choose regtest as our network
|
||||
val network = RegTest
|
||||
// network: RegTest.type = RegTest
|
||||
|
||||
val kmParams = KeyManagerParams(seedPath, purpose, network)
|
||||
// kmParams: KeyManagerParams = KeyManagerParams(/tmp/key-manager-example4040417810562189104/encrypted-bitcoin-s-seed.json,m/84',RegTest)
|
||||
|
||||
val aesPasswordOpt = Some(AesPassword.fromString("password"))
|
||||
// aesPasswordOpt: Some[AesPassword] = Some(Masked(AesPassword))
|
||||
|
||||
val km = BIP39KeyManager.initializeWithMnemonic(aesPasswordOpt, mnemonic, None, kmParams)
|
||||
// km: Either[KeyManagerInitializeError, BIP39KeyManager] = Right(org.bitcoins.keymanager.bip39.BIP39KeyManager@a5ad538)
|
||||
|
||||
val rootXPub = km.right.get.getRootXPub
|
||||
// rootXPub: ExtPublicKey = vpub5SLqN2bLY4WeZyQCMFwoLmEJ59EBAukb7Cg7Lg7KmHstK6qxfxzisLahz9KRzSyyChsSeEpUbAXT6pgPq7CLGcGWa8bYZZFPFsWkwxTCZtj
|
||||
|
||||
println(rootXPub)
|
||||
// vpub5SLqN2bLY4WeZyQCMFwoLmEJ59EBAukb7Cg7Lg7KmHstK6qxfxzisLahz9KRzSyyChsSeEpUbAXT6pgPq7CLGcGWa8bYZZFPFsWkwxTCZtj
|
||||
```
|
||||
|
||||
Which should print something that looks like this
|
||||
|
||||
`vpub5SLqN2bLY4WeXxMqwJHJFBEwxSscGB2uDUnsTS3edVjZEwTrQDFDNqoR2xLqARQPabGaXsHSTenTRcqm2EnB9MpuC4vSk3LqSgNmGGZtuq7`
|
||||
|
||||
which is a native segwit `ExtPubKey` for the regtest network!
|
||||
|
||||
You can always change the `network` or `purpose` to support different things. You do _not_ need to initialize the key manager
|
||||
again after initializing it once. You can use the same `mnemonic` for different networks, which you control `KeyManagerParams`.
|
||||
|
||||
```scala
|
||||
//let's create a nested segwit key manager for mainnet
|
||||
val mainnetKmParams = KeyManagerParams(seedPath, HDPurposes.SegWit, MainNet)
|
||||
// mainnetKmParams: KeyManagerParams = KeyManagerParams(/tmp/key-manager-example4040417810562189104/encrypted-bitcoin-s-seed.json,m/84',MainNet)
|
||||
|
||||
//we do not need to all `initializeWithMnemonic()` again as we have saved the seed to dis
|
||||
val mainnetKeyManager = BIP39KeyManager.fromMnemonic(mnemonic, mainnetKmParams, None, Instant.now)
|
||||
// mainnetKeyManager: BIP39KeyManager = org.bitcoins.keymanager.bip39.BIP39KeyManager@60126619
|
||||
|
||||
val mainnetXpub = mainnetKeyManager.getRootXPub
|
||||
// mainnetXpub: ExtPublicKey = zpub6jftahH18ngZyAAfgh6JB7cJm1oxwPiamekzUFgsHKPQXW6sgbeyMbDG4y9mz5beqGLfe9CiRowedy8ehtrPTYzv3VPEuCXLLmmLWKzoMeY
|
||||
|
||||
println(mainnetXpub)
|
||||
// zpub6jftahH18ngZyAAfgh6JB7cJm1oxwPiamekzUFgsHKPQXW6sgbeyMbDG4y9mz5beqGLfe9CiRowedy8ehtrPTYzv3VPEuCXLLmmLWKzoMeY
|
||||
```
|
||||
|
||||
Which gives us something that looks like this
|
||||
|
||||
`zpub6jftahH18ngZw98KGjRo5XcxeKTQ2eztsvskb1dC9XF5TLimQquTs6Ry7nBBA425D9joXmfgJJCexmJ1u2SELJZJfRi95gcnXadLpZzYb5c`
|
||||
|
||||
which is a p2sh wrapped segwit `ExtPubKey` for the bitcoin main network!
|
||||
|
||||
#### Creating a key manager from existing mnemonic
|
||||
|
||||
To create a `KeyManager` from existing mnemonic you need to specify the `seedPath` and then construct the `KeyManagerParams` that you would like.
|
||||
|
||||
Finally you call `KeyManager.fromParams()` that reads the mnemonic from disk and create's the key manager
|
83
website/versioned_docs/version-1.9.2/node/node-api.md
Normal file
83
website/versioned_docs/version-1.9.2/node/node-api.md
Normal file
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
id: version-1.9.2-node-api title: Node API
|
||||
title: node-api title: Node API
|
||||
original_id: node-api title: Node API
|
||||
---
|
||||
|
||||
|
||||
### NodeAPI
|
||||
|
||||
The NodeApi is how the wallet project retrieves relevant node data like blocks. This allows the wallet for example to
|
||||
retrieve blocks for finding its relevant transactions.
|
||||
|
||||
Since this is an API it can be hooked up to the `node` module of bitcoin-s but it can also be linked to any other
|
||||
implementation of your choosing. This allows you to use the bitcoin-s wallet in any schema that you want.
|
||||
|
||||
The functions that the NodeApi supports are:
|
||||
|
||||
```scala
|
||||
trait NodeApi {
|
||||
|
||||
/** Request the underlying node to download the given blocks from its peers and feed the blocks to [[org.bitcoins.node.NodeCallbacks]] */
|
||||
def downloadBlocks(blockHashes: Vector[DoubleSha256Digest]): Future[Unit]
|
||||
}
|
||||
```
|
||||
|
||||
## Downloading blocks with bitcoind
|
||||
|
||||
As an example, we will show you how to use the `NodeApi` and bitcoind to download blocks for a wallet.
|
||||
|
||||
```scala
|
||||
implicit val system: ActorSystem = ActorSystem(s"node-api-example")
|
||||
implicit val ec: ExecutionContextExecutor = system.dispatcher
|
||||
implicit val walletConf: WalletAppConfig =
|
||||
BitcoinSTestAppConfig.getNeutrinoTestConfig().walletConf
|
||||
|
||||
// let's use a helper method to get a v19 bitcoind
|
||||
// and a ChainApi
|
||||
val instance = BitcoindInstanceLocal.fromConfigFile(BitcoindConfig.DEFAULT_CONF_FILE)
|
||||
val bitcoind = BitcoindV19RpcClient(instance)
|
||||
val chainApi = BitcoinSWalletTest.MockChainQueryApi
|
||||
val aesPasswordOpt = Some(AesPassword.fromString("password"))
|
||||
|
||||
// This function can be used to create a callback for when our node api calls downloadBlocks,
|
||||
// more specifically it will call the function every time we receive a block, the returned
|
||||
// NodeCallbacks will contain the necessary items to initialize the callbacks
|
||||
def createCallback(processBlock: Block => Future[Unit]): NodeCallbacks = {
|
||||
lazy val onBlock: OnBlockReceived = { block =>
|
||||
processBlock(block)
|
||||
}
|
||||
NodeCallbacks(onBlockReceived = Vector(onBlock))
|
||||
}
|
||||
|
||||
// Here is a super simple example of a callback, this could be replaced with anything, from
|
||||
// relaying the block on the network, finding relevant wallet transactions, verifying the block,
|
||||
// or writing it to disk
|
||||
val exampleProcessBlock = (block: Block) =>
|
||||
Future.successful(println(s"Received block: ${block.blockHeader.hashBE}"))
|
||||
val exampleCallback = createCallback(exampleProcessBlock)
|
||||
|
||||
// Here is where we are defining our actual node api, Ideally this could be it's own class
|
||||
// but for the examples sake we will keep it small.
|
||||
val nodeApi = new NodeApi {
|
||||
|
||||
override def broadcastTransactions(transactions: Vector[Transaction]): Future[Unit] = {
|
||||
FutureUtil.sequentially(transactions)(bitcoind.sendRawTransaction(_)).map(_ => ())
|
||||
}
|
||||
|
||||
override def downloadBlocks(
|
||||
blockHashes: Vector[DoubleSha256Digest]): Future[Unit] = {
|
||||
val blockFs = blockHashes.map(hash => bitcoind.getBlockRaw(hash))
|
||||
Future.sequence(blockFs).map(_ => ())
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, we can initialize our wallet with our own node api
|
||||
val wallet =
|
||||
Wallet(nodeApi = nodeApi, chainQueryApi = chainApi, feeRateApi = ConstantFeeRateProvider(SatoshisPerVirtualByte.one))
|
||||
|
||||
// Then to trigger the event we can run
|
||||
val exampleBlock = DoubleSha256Digest(
|
||||
"000000000010dc23dc0d5acad64667a7a2b3010b6e02da4868bf392c90b6431d")
|
||||
wallet.nodeApi.downloadBlocks(Vector(exampleBlock))
|
||||
```
|
212
website/versioned_docs/version-1.9.2/oracle/oracle-server.md
Normal file
212
website/versioned_docs/version-1.9.2/oracle/oracle-server.md
Normal file
|
@ -0,0 +1,212 @@
|
|||
---
|
||||
id: version-1.9.2-oracle-server
|
||||
title: Oracle Server
|
||||
original_id: oracle-server
|
||||
---
|
||||
|
||||
The Oracle Server is a DLC Oracle with functionality for creating events and attesting to them.
|
||||
You can interact with the oracle server with `bitcoin-s-cli` or `curl`
|
||||
|
||||
The following a guide is for interacting with the oracle
|
||||
If you are looking for the documentation on how to build the oracle server,
|
||||
checkout [this page](build-oracle-server.md).
|
||||
|
||||
Note: It is safe to back up the `oracle.sqlite` file to a public place. The seed file contains
|
||||
the cryptographic seed information. You need both the database and the seed file to restore the oracle.
|
||||
Make sure you don't back the seed file to a place that is not safe.
|
||||
|
||||
## Server Endpoints
|
||||
|
||||
- `getpublickey` - Get oracle's public key
|
||||
- `getstakingaddress` - Get oracle's staking address
|
||||
- `listannouncements` - Lists all event names
|
||||
- `createenumannouncement` `label` `maturationtime` `outcomes` - Registers an oracle enum event
|
||||
- `label` - Label for this event
|
||||
- `maturationtime` - The earliest expected time an outcome will be signed, given in ISO 8601 format
|
||||
- `outcomes` - Possible outcomes for this event
|
||||
- `createnumericannouncement` `name` `maturationtime` `minvalue` `maxvalue` `unit` `precision` - Registers an oracle event that uses digit decomposition when signing the number
|
||||
- `name`- Name for this event
|
||||
- `maturationtime` - The earliest expected time an outcome will be signed, given in ISO 8601 format
|
||||
- `minvalue` - Minimum value of this event
|
||||
- `maxvalue` - Maximum value of this event
|
||||
- `unit` - The unit denomination of the outcome value
|
||||
- `precision` - The precision of the outcome representing the base exponent by which to multiply the number represented by the composition of the digits to obtain the actual outcome value.
|
||||
- `createdigitdecompannouncement` `name` `maturationtime` `base` `numdigits` `unit` `precision` `[signed]` - Registers an oracle event that uses digit decomposition when signing the number
|
||||
- `name`- Name for this event
|
||||
- `maturationtime` - The earliest expected time an outcome will be signed, given in epoch second
|
||||
- `base` - The base in which the outcome value is decomposed
|
||||
- `numdigits` - The max number of digits the outcome can have
|
||||
- `unit` - The unit denomination of the outcome value
|
||||
- `precision` - The precision of the outcome representing the base exponent by which to multiply the number represented by the composition of the digits to obtain the actual outcome value.
|
||||
- `--signed`- Whether the outcomes can be negative
|
||||
- `deleteannouncement` `name` - <b>WARNING THIS CAN LEAD TO DLCs NOT SETTLING IF USERS HAVE BUILT DLCS OFF OF THIS ANNOUNCEMENT. USE WITH CARE.</b>
|
||||
- `name` - Name for this event
|
||||
- `deleteattestation` `name` - <b>WARNING THIS CAN LEAD TO PRIVATE KEY LEAK IF YOU SIGN ANOTHER ATTESTATION AFTER DELETING A PREVIOUS ONE. USE WITH CARE.</b>
|
||||
- `name` - Name for this event
|
||||
- `getannouncement` `event` - Get an event's details
|
||||
- `eventName` - The event's name
|
||||
- `signenum` `event` `outcome` - Signs an outcome of an enumerated announcement
|
||||
- `eventName` - The event's name
|
||||
- `outcome`- Outcome to sign for this event
|
||||
- `signdigits` `event` `outcome` - Signs an event
|
||||
- `eventName` - The event's name
|
||||
- `outcome` - Number to sign for this event
|
||||
- `getsignatures` `event` - Get the signatures from a signed event
|
||||
- `eventName` - The event's name
|
||||
- `signmessage` `message` - Signs the SHA256 hash of the given string using the oracle's signing key
|
||||
- `message` - Message to hash and sign
|
||||
- `setoraclename` `oraclename` Sets the oracle name in the database
|
||||
- `getoraclename` gets the oraclename for the database
|
||||
|
||||
### Create Event Example
|
||||
|
||||
Bitcoin-S CLI:
|
||||
```bash
|
||||
bitcoin-s-cli createenumannouncement test "2030-01-03T00:30:00.000Z" "outcome1,outcome2,outcome3"
|
||||
fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374
|
||||
|
||||
bitcoin-s-cli getannouncement test
|
||||
{
|
||||
"nonces": [
|
||||
"80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f"
|
||||
],
|
||||
"eventName": "test",
|
||||
"signingVersion": "DLCOracleV0SigningVersion",
|
||||
"maturationTime": "2030-01-03T00:30:00.000Z",
|
||||
"announcementSignature": "ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb90",
|
||||
"eventDescriptorTLV": "fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d6533",
|
||||
"eventTLV": "fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374",
|
||||
"announcementTLV": "fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374",
|
||||
"attestations": null,
|
||||
"signatures": null,
|
||||
"outcomes": [
|
||||
"outcome1",
|
||||
"outcome2",
|
||||
"outcome3"
|
||||
],
|
||||
"signedOutcome": null
|
||||
}
|
||||
|
||||
|
||||
bitcoin-s-cli signenum test "outcome1"
|
||||
fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531
|
||||
|
||||
bitcoin-s-cli getsignatures test
|
||||
fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531
|
||||
```
|
||||
|
||||
CURL:
|
||||
```bash
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "createenumannouncement", "params": ["testEvent", "2030-01-03T00:30:00.000Z", ["outcome1", "outcome2", "outcome3"]]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","error":null}
|
||||
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getannouncement", "params": ["testEvent"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":{"nonces":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f"],"eventName":"test","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb90","eventDescriptorTLV":"fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d6533","eventTLV":"fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","announcementTLV":"fdd824b0ba0f08e9becbf77019e246ca8a80c027585634dc1aed4b7f67442ada394b40dcb242d8a8c84893a752b93f30ff07525b0604382255ec7392fcc6f230140feb905f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd8224c000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f657131d1fdd8061d0003086f7574636f6d6531086f7574636f6d6532086f7574636f6d65330474657374","attestations":["33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"signatures":["80e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e"],"outcomes":["outcome1","outcome2","outcome3",],"signedOutcome": null},"error":null}
|
||||
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signenum", "params": ["testEvent", "outcome1"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":"fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531","error":null}
|
||||
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getsignatures", "params": ["testEvent"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":["fdd8687004746573745f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115000180e550759cb6275f6db3fad2b616ed51bdcccc204d0d978cd921cafae9fc1d6f33fd84ba8eea0a75f1568149f42e8466e1bc3422ea449532d4eeffad8586d14e086f7574636f6d6531"],"error":null}
|
||||
```
|
||||
|
||||
### Numeric Example
|
||||
|
||||
Bitcoin-S CLI:
|
||||
|
||||
```bash
|
||||
bitcoin-s-cli createnumericannouncement exampleNumeric "2030-01-03T00:30:00.000Z" -1000 1000 "units" 0
|
||||
fdd824fd010bfc52dab25169eef25815c795128f38ef3b89bc7f53d1d788b4a1c544e5bebfbf6799975b62a1888e2d77445b6d002672f52f8626b1ea6cc6cd974a8039d28a9f5f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822a70004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca5071f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b781492057b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d2949305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd66657131d1fdd80a0f000a0105756e6974730000000000030d6578616d706c654465636f6d70
|
||||
|
||||
bitcoins-cli getannouncement exampleNumeric
|
||||
{
|
||||
"nonces": [
|
||||
"012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca5071",
|
||||
"49305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd66",
|
||||
"7b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d29",
|
||||
"f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205"
|
||||
],
|
||||
"eventName": "exampleNumeric",
|
||||
"signingVersion": "DLCOracleV0SigningVersion",
|
||||
"maturationTime": "2030-01-03T00:30:00.000Z",
|
||||
"announcementSignature": "fc52dab25169eef25815c795128f38ef3b89bc7f53d1d788b4a1c544e5bebfbf6799975b62a1888e2d77445b6d002672f52f8626b1ea6cc6cd974a8039d28a9f",
|
||||
"eventDescriptorTLV": "fdd80a0f000a0105756e697473000000000003",
|
||||
"eventTLV": "fdd822a70004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca507149305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd667b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d29f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205657131d1fdd80a0f000a0105756e6974730000000000030d6578616d706c654465636f6d70",
|
||||
"announcementTLV": "fdd824fd010bfc52dab25169eef25815c795128f38ef3b89bc7f53d1d788b4a1c544e5bebfbf6799975b62a1888e2d77445b6d002672f52f8626b1ea6cc6cd974a8039d28a9f5f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822a70004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca507149305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd667b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d29f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205657131d1fdd80a0f000a0105756e6974730000000000030d6578616d706c654465636f6d70",
|
||||
"attestations": null,
|
||||
"signatures": null,
|
||||
"outcomes": [
|
||||
[
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"
|
||||
],
|
||||
[
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"
|
||||
],
|
||||
[
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"
|
||||
],
|
||||
[
|
||||
"+",
|
||||
"-"
|
||||
]
|
||||
],
|
||||
"signedOutcome": null
|
||||
}
|
||||
|
||||
|
||||
bitcoin-s-cli signdigits exampleNumeric 123
|
||||
fdd868fd01380d6578616d706c654465636f6d705f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e521150004012d73a453bb630fe355830a81727cf2fb10c41ccfee040c529a4dec21ca5071a853a189b9acffa2488542c4998261866ce392dbf38031509ceff34077431e65f5aff60ac9ef8425ae438e84a6f067952d60b947e9e44bfc6e8fd89b78149205773713008d316640b74d04f180b6c3c09b8de11b29cd7474681a7ad869857cd57b1db5da37f1c10bfcaf7a4fb0e9f6dbb8d25dfed7a25241bbec3c0a60a40d294f2222871b23a823acbfa552478ae3d526377a8918b346d6e206156c3e5a2c8549305ff92f679598a11e7a857beef901903fc83624413831a06513da577cdd66c03ed28ef6f7b0f48f974b61811a571652ea2eafda5fd5b244674420deb294e8012b013101320133
|
||||
```
|
||||
|
||||
CURL:
|
||||
|
||||
```bash
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "createnumericannouncement", "params": ["numericExample", "2030-01-03T00:30:00.000Z", -1000, 1000, "units", 0]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac0004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf37051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd4756217139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","error":null}
|
||||
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getannouncement", "params": ["numericExample"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":{"nonces":["7051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4","7139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2","7446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621","d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3"],"eventName":"numericExample","signingVersion":"DLCOracleV0SigningVersion","maturationTime":"2030-01-03T00:30:00.000Z","announcementSignature":"647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b57","eventDescriptorTLV":"fdd80a0f000a0105756e697473000000000003","eventTLV":"fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","announcementTLV":"fdd824fd0110647c85d333aa6fc0d7808201da9d1010b815710dc25c3d73e9cc7a7f372a7342c99144ba74d70be72920f4515daa6565bce12aedfc5a828ee37b5453454c1b575f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e52115fdd822ac00047051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c47139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d27446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3657131d1fdd80a0f000a0105756e697473000000000003126578616d706c6544696769744465636f6d70","attestations":null,"signatures":null,"outcomes":[["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["0","1","2","3","4","5","6","7","8","9"],["+","-"]],"signedOutcome": null},"error":null}
|
||||
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "signdigits", "params": ["numericExample", 123]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":"fdd868fd013d126578616d706c6544696769744465636f6d705f6f49e116de8cb57856bacdd9997d8dfb73877f64a4ec8d45fc0e73a0e521150004d72282a2e9532924dc8cd79685a501202332ad0d118166328cb76138414fccf3d0646c9efd9523274014841ba24bf63219d5650d1682209d7e48af009d58e6d87051e50fd1ab30df4717da8905e400a32c5f4d793a4ac5433ed416165dd286c4c025dfd1e39de77e0418fa7d39abf2e9daf55d7fe34f8e312368cb4d45b4d4b97446ab1d71a550a0d604c3e86c40a3c9b12de8f08a86639068707822cd475621700347c52af088eda9a0245385094518134e73bb997102e11f6de0aeb36af7237139d7cabd19d6b0b9e827cdf84a4fc18c88d1882e4e096d8dfeff58759504d2f9e7a9e183b0836ad58dd646d9ab123132397109e4f51c5842958932a81bacd1012b013101320133","error":null}
|
||||
```
|
||||
|
||||
### Set oracle name example
|
||||
```
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "setoraclename", "params" : ["MY_ORACLE_NAME"]}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":"issue-34","error":null}
|
||||
```
|
||||
|
||||
You can retrieve the oracle name with
|
||||
|
||||
```
|
||||
curl --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getoraclename", "params" : []}' -H "Content-Type: application/json" http://127.0.0.1:9998/
|
||||
{"result":"MY_ORACLE_NAME","error":null}
|
||||
```
|
92
website/versioned_docs/version-1.9.2/secp256k1/secp256k1.md
Normal file
92
website/versioned_docs/version-1.9.2/secp256k1/secp256k1.md
Normal file
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
id: version-1.9.2-secp256k1
|
||||
title: Secp256k1
|
||||
original_id: secp256k1
|
||||
---
|
||||
|
||||
[Libsecp256k1](https://github.com/bitcoin-core/secp256k1) is used to preform cryptographic operations on the secp256k1 curve.
|
||||
This is the curve that bitcoin uses. There is a _signficant_ speedup when using this library compared to java crypto libraries
|
||||
like bouncy castle.
|
||||
|
||||
In bitcoin-s, we support native binaries for libsecp256k1
|
||||
|
||||
1. [linux 32 bit](../../secp256k1jni/natives/linux_32)
|
||||
2. [linux 64 bit](../../secp256k1jni/natives/linux_64)
|
||||
3. [mac osx 64 bit](../../secp256k1jni/natives/osx_64)
|
||||
4. [windows 64 bit](../../secp256k1jni/natives/windows_64)
|
||||
|
||||
Bitcoin-s uses a zero dependency library called [`native-lib-loader`](https://github.com/scijava/native-lib-loader).
|
||||
That does the appropriate loading of the library onto your classpath to be accessed.
|
||||
|
||||
### Using libsecp256k1
|
||||
|
||||
To tell if you have access to libsecp256k1 you can do the following
|
||||
|
||||
|
||||
```scala
|
||||
val isEnabled = org.bitcoin.Secp256k1Context.isEnabled()
|
||||
|
||||
println(s"Secp256k1Context.isEnabled=${isEnabled}")
|
||||
```
|
||||
|
||||
If libsecp256k1 is enabled, you can use [NativeSecp256k1](/api/org/bitcoin/NativeSecp256k1)
|
||||
with static method defined in the class.
|
||||
|
||||
|
||||
```scala
|
||||
val privKey = ECPrivateKey.freshPrivateKey
|
||||
val pubKey = privKey.publicKey
|
||||
val dataToSign = DoubleSha256Digest.empty
|
||||
|
||||
val signature = NativeSecp256k1.sign(dataToSign.bytes.toArray, privKey.bytes.toArray)
|
||||
|
||||
val verify = NativeSecp256k1.verify(dataToSign.bytes.toArray, signature, pubKey.bytes.toArray)
|
||||
|
||||
println(s"Verified with NativeSecp256k1 signature=${verify}")
|
||||
|
||||
//you can also just directly sign with the ECKey interface:
|
||||
val signature2 = privKey.sign(dataToSign)
|
||||
|
||||
val verified2 = pubKey.verify(dataToSign, signature2)
|
||||
|
||||
println(s"Verified with NativeSecp256k1 again=${verified2}")
|
||||
```
|
||||
|
||||
### When libsecp256k1 isn't available, or you want to turn it off
|
||||
|
||||
There are two reasons you wouldn't want to use libsecp256k1
|
||||
|
||||
1. You don't trust the pre-compiled binaries we are using
|
||||
2. Your OS/arch is not supported
|
||||
|
||||
There are two ways you can circumvent libsecp256k1
|
||||
|
||||
1. Set `DISABLE_SECP256K1=true` in your environment variables. This will force `CryptoContext.default` to return false which will make Bitcoin-S act like `Secp256k1Context.isEnabled()` has returned false.
|
||||
2. Call Bouncy castle methods in `ECKey`.
|
||||
|
||||
Here is an example of calling bouncy castle methods in `ECKey`
|
||||
|
||||
```scala
|
||||
val privKey = ECPrivateKey.freshPrivateKey
|
||||
// privKey: ECPrivateKey = Masked(ECPrivateKey)
|
||||
// calls bouncy castle indirectly via CryptoContext
|
||||
val publicKey = privKey.publicKey
|
||||
// publicKey: ECPublicKey = ECPublicKey(03a9e51ff5e03f25f0240cab576cef27cf4b793de086b711b4c2388c5dc1451763)
|
||||
val dataToSign = DoubleSha256Digest.empty
|
||||
// dataToSign: DoubleSha256Digest = DoubleSha256Digest(0000000000000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
// calls bouncy castle indirectly via CryptoContext
|
||||
val signature = privKey.sign(dataToSign.bytes)
|
||||
// signature: ECDigitalSignature = ECDigitalSignature(304402203227ec8c9e5a6fac2acd70c8c6f08d9f90941821d25cc046007f448e78caecc80220781ad462e7c862df211bee1dd81b597327fa35f78a26c4501ebfd7f81bec7e7a)
|
||||
|
||||
// calls bouncy castle indirectly via CryptoContext
|
||||
val verified = publicKey.verify(dataToSign.bytes, signature)
|
||||
// verified: Boolean = true
|
||||
|
||||
println(s"Verified with bouncy castle=${verified}")
|
||||
// Verified with bouncy castle=true
|
||||
```
|
||||
|
||||
### Building libsecp256k1
|
||||
|
||||
[See instructions here](add-to-jni.md#adding-to-bitcoin-s)
|
235
website/versioned_docs/version-1.9.2/security.md
Normal file
235
website/versioned_docs/version-1.9.2/security.md
Normal file
|
@ -0,0 +1,235 @@
|
|||
---
|
||||
id: version-1.9.2-security
|
||||
title: Security
|
||||
original_id: security
|
||||
---
|
||||
|
||||
The Bitcoin-S developers take security very seriously. This library has
|
||||
very few dependencies (at least in the `core` module), which is for
|
||||
security reasons.
|
||||
|
||||
## Disclosure
|
||||
|
||||
If you have any security disclosures related to Bitcoin-S, please send an
|
||||
email to either [stewart.chris1234@gmail.com](mailto:stewart.chris1234@gmail.com?subject=Bitcoin-S%20Security%20Disclosure),
|
||||
[nadavk25@gmail.com](mailto:nadavk25@gmail.com?subject=Bitcoin-S%20Security%20Disclosure),
|
||||
or [benthecarman@live.com](mailto:benthecarman@live.com?subject=Bitcoin-S%20Security%20Disclosure).
|
||||
|
||||
If you want to encrypt said email (which you should), Ben's key is available on [his Keybase](https://keybase.io/benthecarman/pgp_keys.asc?fingerprint=0ad83877c1f0cd1ee9bd660ad7cc770b81fd22a8), and Chris and Nadav's
|
||||
are posted below:
|
||||
|
||||
Chris:
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBF/o21sBEACr+4VIiujUqdXjxW7+6yle7zwBhFqYkj3PsFyLMcbrYvzlUlDb
|
||||
IUQVXzYntqCQYVPxwu8OYxTHbrpM0H1cknfTkdT+lEVvNbyegC6M9x+hYIrpoLXx
|
||||
klrKAjfyhRbxHOLZ4fbfxzVll1htj16wWOoGfONDC6OblDWZ2tlC6qexIatxhTu7
|
||||
+obdg/gQHx/uP7QhTjyTgj4XJ4uCS/lLD/7ZTFyNjqzIHd/ErEJkULES0hXv+ZzT
|
||||
mnP9SLRdEd3D5OmcN6xCR85MN78cup0ZhkF72yct+XSwxHrgcfWpaKJMU9E0O1Bs
|
||||
YVjah3rYY0T96Wlvl4A1Mg/V7X0CaqhVhzMuAG6OJ76M+JOMvzkugJ43d/93861h
|
||||
7DE/5ct6qKHD2LmAqynZUQmvv10De01v6RdZz+twTAx77fYOmPJx36LI8TWXHD4d
|
||||
tpr2teNlpG7RVmeGEZj6iiYpTroJScikI3dzu9nEqbGmxSPZ7rbJ8/Z2h3vb7M4L
|
||||
bHRnG9EfQZeUZlUeHFiEUdQUzRyg/cMsPtIPgv9yKDYoL3noN/jQykUqVMdBEppz
|
||||
Jn7jU0Z/o4rwH7Lasmg1Ft0uVZouW8MpKsKEMViE9kcxZGeSeS0vlzBQkV5IA0j0
|
||||
+nrQzgDZ7gcdaFusfaeXBPIXFCQg0gOSfwxmLIM2brHGq/rU25g5wyT4JwARAQAB
|
||||
tCtDaHJpcyBTdGV3YXJ0IDxzdGV3YXJ0LmNocmlzMTIzNEBnbWFpbC5jb20+iQJU
|
||||
BBMBCgA+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEkjT01q9Hxxt0GjkP
|
||||
iXbKCvcaeioFAmJdt0sFCQY3QvAACgkQiXbKCvcaeir10g/+O2A7slXJsu232Lhs
|
||||
3sq9YWk1AjjhIXMr1D78F8YdBm3StZQNkdHtD7dP0lIHzfighbQi46TAMUrZdIJ5
|
||||
Ls6ZDyEoFDlGTfPDY5a34FeMbBS/5ZNHiuYgpmmDAv2Pzx40husUb22AKGM8LYzB
|
||||
bFXJHKy3hu5GvpIvlYhJQM9QOYddMMBg2kiBcmnsRkCINKh78hy2kRKbt6ObmxoL
|
||||
zu2qD7VXlnFClYNJUtO7iNOMqmXOSgKnPgsBRtR044Ag9m8CP/fyS3x6nQMGFQDi
|
||||
EU8z2nbq8iqkL+sc5oxiHD0jwqeVlRRUeHlkbh+lQi5SjKddRA3gzZMRANmt4Vrp
|
||||
ZF9rjoOsHLNi7jkKl9rvKhAuWZU2KPCb7KFjAe6VdF9TQajv1XJyl3AZN/LN1ClA
|
||||
++4xJnzaEt3MV3rFkiAyg2iFQxV9CWSJwdO7GM2zAwKSetndAdctk8iJ1vlacNcA
|
||||
wV9amjqI0odbnCfjYpbSUH7CeyVIvsa+7XGuk75zCvURHdSddaKZXDXw6mXjOkBJ
|
||||
UPF8e70zmFK06+JT9dnPNmGuZK1+GO1/sK3Ts0H/M6w3lxsy1tHAOLLzHpwdjLzT
|
||||
hae1UWRmMJzkYYfYt0m2ujt2UbMvZ+qDVlgHsx2WVZGghd3vUA+itFWdoo3w3vyz
|
||||
PsEyW/DR/pywQVKEWQfZGSPFlkS5Ag0EX+jbWwEQAMMbD9LxLdSTwYcxIo9hqG8y
|
||||
kl7r5sX0qI3rPHACY/qU1amXt632gRXhHLcP5PnTqJR7C7LLPAiBGg80AtczXcOC
|
||||
b8XTWwYQBLMNBtijfElXZkHyCU+BOPaBWes+noYb1c/Fi96t/ZbptjapDP6nMO8z
|
||||
dhec0M5cXbIKLrCcEvHIXsgAjxPFxH023s+rjXgAcFk2OFc4B5353dDHXMFPAM5u
|
||||
jx4xt0nxoSOUCobBvOOKFOsryj48ckjVFGysk4OBWBYWW5kW2WbhyRRPBrVLOO+Y
|
||||
hO6VQ+XkpFVnwUzp0gfmNEZbUQ/ot09+zcLK1HTHeXGEEyefnbFQIHoO4lPhTDmc
|
||||
VC8DNXbaOAsPEQV12C5JiKFS79DWETxKtlqdEyjIGyqEtj83hcomJkyMf5wCTg/B
|
||||
Jq55yPyl3gi1cvJ4LIjZv/wpY/7BcvhtCJwPLNs/1m1UsGXLz51/R8CWcK0TGTX5
|
||||
m+qqpBEhWy20epqxnXxjsOQVNSKPskmLS/nGpCneN3XfoTOEQ+olrxlZyXtvvO72
|
||||
B23T60Rtooiht5GUlyvvIj3Fsc3w4oB6MoMEEOmV4feWyvPbW3WKrDDpxA8VxwZj
|
||||
gofYdmvFcHtDO3joBiPQ5vUwMpH25DBBePdjrl1JBokLUn8GvUwgc9no8PxrXg2a
|
||||
x9Rhvtok3TVmIQXZPgTTABEBAAGJAjwEGAEKACYWIQSSNPTWr0fHG3QaOQ+JdsoK
|
||||
9xp6KgUCX+jbWwIbDAUJA8JnAAAKCRCJdsoK9xp6Kv/RD/92WAfrBRNTPG/R8Zjt
|
||||
8q8GfViyaE+286hqRJwzv0YtxcFGWRb7f4SfWDLF3HZ2NCkElBKLqw0GOgHsJH4T
|
||||
QVPNhKoyjD08hO/EXQ8eVSaDFpmdRwSCfzPlJvEcunbLkU2AwuoZSTE3cSORh8DF
|
||||
qMFUwLKxTq8qHHsUNrKl8Zt8iNM2rZ8KBoKG2w+SGW+YOVq8Ug7yvlGlDrOvOucc
|
||||
VD+hWMEOLXO3z2t1mAd8wgAdPqdx+CZM/sbJfVS4t+IiXaqGCqJ5bPqlEeZxV21R
|
||||
JWQpsW70xhSPT7EEMp7Q9yBUioZQn7eq6XXYSEzpiTgTFqdh5fkEth3sFBcxEfzQ
|
||||
SqzowmDyv4mFu9YJ5I2xJ3yPhIyStOACS4LApO8jkfhd9ZoMHfDtxfD09YmKOSqC
|
||||
3aVs7UOUvtyaDk5JSELYfbKRp60EOHEpG+vG8MNVu2edaJ8cLY/s4nvhw/vwMT0r
|
||||
GxOjinlrpZNusSTcd2roXROfF1Mvi4y7EujQp6c1eGEP6LkoTB8FXDIm4kDfC6Ax
|
||||
fJT/axKh69/m1oaqeI7FTSYr4iQA2r8eoZbLldAIvNFD4nN8wNph17cCUhUWzZNl
|
||||
UOxgck4j7Mm5KZiB5AzBujUKdwlMgt3rGksfhSOxzI2cR4l4UWpQKjbH43T3DX+8
|
||||
Q9JFZCpM0voRqCBwg0S2dsYf25kCDQRed3ffARAAuqMa6jyDdqc3eknCfDePKzkE
|
||||
tEu0D+KMFwDm5FyMx9CNF2sDmXDwAD5ztTUJ0wAS+11riGFsQHgxqHuQm2RDRnpy
|
||||
nQgQ7DcAdJkLi5MlHRagAyZB0HQHk3rhRcon0iTxgrDnLl69uQFtUA1JX817FnyD
|
||||
4m94M6J6EyPMiuA+f5+n1a644+iQgkOmtDO+JPOQLMiVfpgY0VW5rdL0NHoCU8C8
|
||||
k0wmCkjgaH279ABT46eG9pc6wXPjtCZJj2rNhajRVQ9PEut7RoyPJNpZelj83p/J
|
||||
A3bfsLySNEd43STtNmdQcaYQP5Blnsn4Gsuiyzj8vw5UhOQT8KEmgG+0dlRBACwv
|
||||
yaD/KY3gAgqCHHpFdMVlOsdo9RuKJ5TzdPhiOcmy0EeYixWPOiJIWjTMur/rNC4F
|
||||
LNWSD8fJntZvmGWmOlKWCAy/CEAPXOZ138GVofobW5+3XxOVDlWK+m/bkJZRGqCZ
|
||||
JrPw1GvdgjGjQjbwTFkWsxEKhYOmEdoVfXkf3xezAMMls9KdFKKQJMdUrxq67XD6
|
||||
vRVDaVvn07dOnisCAhEvGtOeVtx/IAR9nRUllr/RmUokNP+hNY36iIuNjZSHXdsm
|
||||
J07oyKymbdIcsbUunqgLKJEX1+fts1BSWWDrq0HLhLKlvwbPEH5+W6WrKW23C/UR
|
||||
LhF5hMAKdzsQgVJLNfEAEQEAAbQrQ2hyaXMgU3Rld2FydCA8c3Rld2FydC5jaHJp
|
||||
czEyMzRAZ21haWwuY29tPokCVAQTAQoAPhYhBDOaSSKVdgUIGQg+s/mXJIcvgikQ
|
||||
BQJed3ffAhsDBQkDwmcABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEPmXJIcv
|
||||
gikQ97MP/23L+fpEYRl8GmkIEQmHSRX++2YwXaEtKBFZ2y8+NJFrvs/wsuxWmARA
|
||||
XnBjycI58w29chxA1Kvre37p4uigQKNB3LZ8aEw66R+3SJWiu7SA8SmkjOu6W2az
|
||||
/gEFouhdz7DQUnE5eTayrDk0wkPqtk0vl/WZsww5TSxjED4T0YNmpPZZJoV+8FcT
|
||||
mANd3PGIYq7Ql4qc3KqQu+qis1Y5JX2oTSmLRUZX4id2ZS3Y8hFyaMiMNXA4ZpjR
|
||||
iNIV2q5VG0uD/FMeNwfsdZ2L9LN3dqzOPZTVNrkOSwm9uIfVYipZt6nCeom2uUA2
|
||||
kblsKSCO5gH9T3C2EhzRkexkcZtImahcxv0LjW/5hc8tgGgvE2QEJEHdEXe2aSpU
|
||||
16FrNsqkbTNr44xxG8BhRGbx+HTPbwSDq1fny/wpIzLuWQV5C49qB/ZGEVcZw+x9
|
||||
mumRi+t516lQlRGjy4A3ZlpIMlqen9Ubpjo0BOJ16Snxz/MZvKikuBQK+oAf+69b
|
||||
CeI9KewF2ANWGD/cxBQmdyLaJsjEy4PUvIjtjZY3d2Nn5EyaQnt+ZLMPV+cjlfse
|
||||
D42BRnL3A2HeOLyOuS8ieY+9QmKcS1HSOWupPmApb6U/xvD85ZSEdQfZtEi2DDXm
|
||||
72PNhs2Rpg01/90GsbfsWTah84fjYaaD6ScDVneESWX+3mx+hXwQiQIzBBMBCgAd
|
||||
FiEE4ajEZdDOJZ9vpD+NCJYfQbyb/WcFAl546u0ACgkQCJYfQbyb/We9Ug//VtTv
|
||||
cmXCKSXfPn/LF48HDz/kNKXuDIbJyoKUd2rDPHvzwG0slurjaVCqY5KDDbh39Dnv
|
||||
VnjdstttBMQQJP1HCh62+xPVCH9yI+IJt4EZXt5Onc8xWHab/1H8Xz7T7QlBD7W+
|
||||
aAST1eXBj2d/Rr3SIVfciAbJHC2RWthonHd2nd/bMRDkFNXRB2b9cp2pnVtNnCdK
|
||||
r7C/g6PCDN/BjiV5mTeK8UHrLgf63K4v7VXP8EvoZqgIq9limFMFTHl4Lpc1w9/6
|
||||
pRSC2tO013mhKPo14Zfr30sMQkQelaopbbUtmxG4+xv7E4vB5EdX6rpsE/b5WR7s
|
||||
KI2BOcYJwAZsgXyyqTQv3ts1nmv+dwTZAdBh3bw0c32Gx9kQD8p/85/lNWs2Q03E
|
||||
B1EwkNsYf14rJ0i5r4u1VXfGyI9dgCY2EujBc4eVob2ebnch5F3IQ8ANNx43+ckO
|
||||
rYGiXSQtUBF0p18OHNCQx2ANfcuNimXjKVyaQbeMulyrPQKlarSqBSoBnwQMASOM
|
||||
emYP82hotS6P8dZPx9HbG1HFW8Ibo/rZWy1ecyDJ61GSAuRlCLS/eLdqxHiIg0es
|
||||
vVuvh8NjQUR1YiOogUTTv4+Li0tgnXOsDj1ElhYg3zmCxNdKHXlHGP2PsD3PmbSj
|
||||
7oV5sOY75yxAuCaG0bc2wjnYHItCxDH6cYzYeBy5Ag0EXnd33wEQALGFwe+Wpy1N
|
||||
jHy82jJHEwiK0bJLZ/IDc6Vcn2nVYDEI4C3X+RiEQ+JZ7QZFgW8hiHFaQ40Cx3gA
|
||||
GPGysgPQ6pW+42w1BiDaq3AIqBBAyYJbcc2qRLb04/BAKerfYS7KPzusUGfLXHUF
|
||||
HIYu/p03wOrUVXTFA4tCOnDGQOq+R3D8JQzsGBVSbzkIkZDIgsS/e0Xpp8e/BFOc
|
||||
ol2fQMGrUROFQMiprL0smLpv4qjuYsVWFZd6w+7nHExmf5OndMsNBUhcYcggED8o
|
||||
KtotfFSzJG9YV0G+0yV/6dFzw5wiPkjyN80pDQdT80gEJC1JfWtTXXT+EZ6JpiRR
|
||||
fZyZsA/c8wXJrI+FscvtLWTKzKdMHv7a7gqfFOj9XbxuriZFez3DhyEIOynbjCVG
|
||||
X+U4Nqp7b93BRrNPF8a9DIeVI3IdrK9NclAlHXPeZwVWPUmP3ibf9SE5Asf6dEMt
|
||||
ZBx2MJXlHp6Iy0/pz1a8XIqVrX1H6A8QtjlA+DlWqA/RtVRPa67E96u3d5n5SyQM
|
||||
ua9BE8h55X35+nbIEvu2+PIjZAUAxMrJGzXzeDhHiYeZdGLQ+gu75h0x9jjdeHL3
|
||||
Wqf4IizTJs3Rnvri0PvxJcyheBAvjrOgViFEdMF3MFD5TVxS7Y2w0pxg+aTV0Uve
|
||||
4xR7LBHAeyjOQ8A9wNXh3Pfy+M8wGA+zABEBAAGJAjwEGAEKACYWIQQzmkkilXYF
|
||||
CBkIPrP5lySHL4IpEAUCXnd33wIbDAUJA8JnAAAKCRD5lySHL4IpEJnKD/9ZBlJm
|
||||
aIUchSsZUvgzsas+fqHUPQWkTMHnWFfT3iQwjiQrvjENN3ys6B7sKics+ytfVGDu
|
||||
v1dBsuZ+oQNKjxvpauoCQAo3me7jOIwNghSdbDtOKhr6eC2Eap+6zYSyWhFhVexw
|
||||
w76i4Pv0/+RwJOU8yM9SODwWgE7GyLmcU2TPRCZPZDNUS95+3X/zWUA9cNdYR+JY
|
||||
GN+Vp2Ii1QVADSUe3DCmskdED6EtnHxmF304H5X6Ec/b2XwnC7Ug1FyMGneO96W1
|
||||
2I2jI0Zc8icbDD8Jra+uAk5mR4ysRv8YgE9vBfI2K2LWcN9Xs79MghZ5867Ifvgo
|
||||
6kmQTyd5dNCGwYg5yjOd2pAVtIP8YuSvYqphqrykMyC8AH0mqqRqQAMT8LWo69cJ
|
||||
GU4kVrpArA84u9v0kAbM+LsnzSzCQxrQKeRPJNDrg28X47ANKSnqukqAQiS95uDX
|
||||
AEXslS8cIpgufqbcQubec6ZEvB59MoxoRsVZ2p2VaWFPMakR4ssdiM2Yl8XZDqhU
|
||||
DBQ4v0ELolj9uqH5u5Z6JUL3NnPd4hK4LqYoIPYhgHEjriMB6cslk2dcn//8xjaH
|
||||
4W7Ri6Ud/LpxURnYhu0yULf1X6/79i1cN8WfrDexB5X1WGipNphkuPSHElBnQ2ko
|
||||
O45I+h+PIk8K+cOyekIHrOA3YqR2V6Ck6NjRxJkBjQRg5wkIAQwAznHsEotULAEU
|
||||
AF1JClKcXU+uCzkXl//92rDRh4Czae3NWnX1aF1xLDnAc70uTz1af/7ePSINp9WE
|
||||
QkFVZvTcs/p7IkLRWWFD2owx/zgKlQ5TPklCOBR7iiNPz69olMwaQozl1weqELXH
|
||||
V5z9EwL8Ue4W01YdLbLbHmQggqNMluIHzMZjrG4s2LqqCqUAyVtZFjrDf8y5AjM1
|
||||
IPeuzpi+ejMzYoJahDFIrqX9aPUDdxo7Zl9IxD6YQDV04J9hNwk8zjbySZE/Gigu
|
||||
che5E5iyBFoqgF18ZB1esSrIrmEGmsTrxAFXlhD/bukJQk79M/t8s1hKR8YyEvU/
|
||||
6+tbYWv5Cm3rb3XgtxXNWYikSTAuiz7FljcLhVzPGpeNnZknYqYgrSGmT7L1scyx
|
||||
vEgqzvVauW5ZZ6Ok0Gjs12IBQhNHVX9qrGAaRBWR7Xeaqx+zKX7YBYuvnFuoqBIx
|
||||
PmZ3GjRN74HWM2px+xTJM0Nd9QDTlvOFkfAeYYc9tUKaJv9Jl4hjABEBAAG0OmJp
|
||||
dGNvaW4tcyBzYnQgY2kgcmVsZWFzZSBib3QgPHN0ZXdhcnQuY2hyaXMxMjM0QGdt
|
||||
YWlsLmNvbT6JAdQEEwEKAD4WIQSEmSLZwgcR2bO/1A6dbqmQNjXASQUCYOcJCAIb
|
||||
AwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCdbqmQNjXASQpvC/49
|
||||
1ySjvmI1o/jKaCKs1LgCp/wMBzoLh7A3u1c6uOYDxLFmJVQQhAtWmCXVjYOzNX1J
|
||||
q7sTK9Faj7WJ3/jW3xhdk+Wzf1/YrczYozIe0rRT12uXm+B/o+OAdhvWLmhfXt0X
|
||||
IK26PDr8f9IYeGqv0L15FfWBVk7ajHUtnyVH+0nAStQ5Xc2qKr+1YetQ2M67YnZy
|
||||
eMTkFXdtn99c7QZ734vxomP3cc9ZAyh4UmVzfvvMLyP3w1YFnHIqxEZ9KtNlrvMy
|
||||
6jQEj7//6xs68paiVCgiDVLQTqR/ASP8G++IAR/u3cjUPlb9Ukw0Dals+87DQANR
|
||||
UiYTFh8BT5RydEgiPK6pBYU+gLSySEC0tZeqtCpohAlRpXgGfg1DnVe5/gMCQyLP
|
||||
WAGclyuHtjp4XQkFUwGx4Dhkv93tsvsr30V7bNUA8uHw1MlNChtVkx/mRgjSUGWj
|
||||
yduNcOkVYCWaWGzQPOkS8WvrZaT+smP2TJqLLUtLAFCy0VT8ErJlM3qikHBBPMy5
|
||||
AY0EYOcJCAEMAKzlynw9uYZ6dmKECneu7W8bgYiiWQBoarJJ0Gugb0sGByHnS7I3
|
||||
/UTmFTMYo9O7GHyRqMoEmUMUlHk0Y+tnSVVBHr48bObVjg+xdNKLLHamTXvx7/8a
|
||||
KAaOm4DN+TVdSUNuJNups/P1P9eytdGR/9eXBEg/TTpGswiGwzZ3Qp8tUQvPPUcQ
|
||||
kRWxOdKjsuPQ8xN7vZ5T2fAI/eaATmoIMkSQCjFNKsTxOZ1J8vSKJRgc+WN9CXmx
|
||||
x+yLVPJaJNLESZwadXQmzL1C5fbbyuJHlLejAZDAsIhITHBFafHOr6IxIAVMMAZE
|
||||
wqtrmjaaM/di1rn7ScNLNYP8H07UDX9HqKyii3RF9QuG/44zyNLIgFxOQqGVTXN0
|
||||
/8vPrHC8KDo1UnEmdrerD3tz9PmBNaOdDHIPSRgGHXJt9laGrpRepP/1PMXxjRbr
|
||||
e3wKVH3fX8cgMd7FY4T3JTvhHjH4u/n4mYc8MCT4UELKDqy38bvRv286pIDlcXyH
|
||||
XaM4Yv4U7jfftwARAQABiQG8BBgBCgAmFiEEhJki2cIHEdmzv9QOnW6pkDY1wEkF
|
||||
AmDnCQgCGwwFCQPCZwAACgkQnW6pkDY1wEkngwwAg4IvPXLpzXSzvPoqN9wtEG62
|
||||
fFpwJLKoN6r8MF88EyuWSPLPj0yExpcjBc+9od0xMOWYQwTkfWys87cuzUXkV8/1
|
||||
MPAms3Y/t2Dj3M0iEZmqd+y/Z8zarBX5TxRaVQHdh526zVOOdQQO6Fceeijl1cbr
|
||||
q+RB7flkpvYBqkwT0W1Cc09g6EevpBPqpvh52MReEHYPv4KOA+9myunDjb50Uq/1
|
||||
9ITbCjtnvXmXowmtwE5hgtP4/XDzIkXXAZtDW9+nOkt9v1i8QRT5FzpLZLZV0BSr
|
||||
HoO/afEIKU3LPjh3DG5c3Uf2eIvquGN3TzH6+gtOXhsMtEbOld6x3JfnzVBhBNPo
|
||||
Q7iBGLu0dTJEW/GeikhR9gXBGezT4lwxLegLw54bo02T6LDKezxmioOZzC3KpKio
|
||||
rM91WRd+wRw3jo9acRRO+L7q+liTHNa3Di4fQ6pSDjPh+/YAi4yjiqTeAHIl07w/
|
||||
JbvzfqqPhB9ghQXif0G6O8iK4RzInoC5ojnefCpmmDMEYXXQJxYJKwYBBAHaRw8B
|
||||
AQdAuDLg9NoBShEcFgfYyaorNAxWador8PGa03tTqlLtosO0MUNocmlzIFN0ZXdh
|
||||
cnQgKE1hYykgPHN0ZXdhcnQuY2hyaXMxMjM0QGdtYWlsLmNvbT6ImgQTFgoAQhYh
|
||||
BHaIIg2Gb4aiXdWZZRb3iLyFvNAKBQJhddAnAhsDBQkDwmcABQsJCAcCAyICAQYV
|
||||
CgkICwIEFgIDAQIeBwIXgAAKCRAW94i8hbzQCpWJAQDElqaCni45YGKbxiaKwxSX
|
||||
n7Am70CJ2v0cOd1ndYFu8gEA6pIbyrTZsJ2pdCMwpyTFqtjcugeAgqqQTYpNkWFE
|
||||
9gm4OARhddAnEgorBgEEAZdVAQUBAQdAyxuM5ExkNwv/CEI8pnHo9QxhfWEqXDo+
|
||||
6rJRtD8LOQoDAQgHiH4EGBYKACYWIQR2iCINhm+Gol3VmWUW94i8hbzQCgUCYXXQ
|
||||
JwIbDAUJA8JnAAAKCRAW94i8hbzQCjWYAQCbjvSMmwP1tMC/dprlMAFJQlj2KBxP
|
||||
pb1bQDDpL/mdBwD+Oa6asmZFDfYjk8kIJIHxQhgZQ8ilAOm/ipW8Z1dL1AM=
|
||||
=9yPz
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
||||
Nadav:
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
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
|
||||
yCLXAg==
|
||||
=fx/l
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
96
website/versioned_docs/version-1.9.2/ui-setup.md
Normal file
96
website/versioned_docs/version-1.9.2/ui-setup.md
Normal file
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
id: version-1.9.2-ui-setup
|
||||
title: Installing the DLC Wallet UI
|
||||
original_id: ui-setup
|
||||
---
|
||||
|
||||
# Easy setup
|
||||
|
||||
We have desktop installers for mac, windows and linux. This requires you to be signed into a github account to download.
|
||||
|
||||
The link to the installers is [suredbits.com/bitcoin-s](https://suredbits.com/bitcoin-s)
|
||||
|
||||
You can download the appropriate installer for your machine
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
After unzipping, you will need to run `chmod +x ./bin/bitcoin-s-server` from the terminal make the file executable.
|
||||
|
||||
After making the file executable, you can start the server with
|
||||
|
||||
```
|
||||
unzip bitcoin-s-server.zip
|
||||
cd bitcoin-s-server
|
||||
chmod +x ./bin/bitcoin-s-server
|
||||
./bin/bitcoin-s-server
|
||||
```
|
||||
|
||||
This starts the backend and will begin synchronizing with the bitcoin network.
|
||||
|
||||
|
||||
### Building and starting the frontend
|
||||
|
||||
Here are the instructions to build, you can paste this into your terminal
|
||||
|
||||
```
|
||||
git clone https://github.com/bitcoin-s/bitcoin-s-ts.git
|
||||
cd bitcoin-s-ts
|
||||
cd wallet-server-ui && npm i && npm run build
|
||||
cd ../wallet-server-ui-proxy && npm i && npm run startlocal
|
||||
```
|
||||
|
||||
The last command, `npm run startlocal` should result in server starting with logs that look like this
|
||||
|
||||
```
|
||||
> wallet-server-ui-proxy@1.9.0 startlocal
|
||||
> DEFAULT_UI_PASSWORD=none BITCOIN_S_SERVER_RPC_PASSWORD=password npx ts-node server.ts
|
||||
|
||||
...
|
||||
|
||||
ConfigureServerURL() http://localhost:9999/
|
||||
ConfigureAuthorizationHeader() Basic Yml0Y29pbnM6cGFzc3dvcmQ=
|
||||
[HPM] Proxy created: / -> http://localhost:9999/
|
||||
[HPM] Proxy rewrite rule created: "^/api/v0" ~> ""
|
||||
[HPM] Proxy created: / -> ws://localhost:19999/events
|
||||
[HPM] Proxy rewrite rule created: "^/websocket" ~> ""
|
||||
2022-03-11T17:05:19.238Z info: starting HTTP server
|
||||
2022-03-11T17:05:19.242Z info: Web Server started on port: 3002 ⚡
|
||||
```
|
||||
|
||||
Now if you navigate to your web browser, you should see a page like this at `http://localhost:3002`
|
||||
|
||||

|
||||
|
||||
The password is `none`, enter that and you should see 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.
|
||||
|
||||
After the synchronization is done, you should be good to do a DLC! :tada:
|
|
@ -0,0 +1,319 @@
|
|||
---
|
||||
id: version-1.9.2-wallet-election-example
|
||||
title: Wallet Election Example
|
||||
original_id: wallet-election-example
|
||||
---
|
||||
|
||||
This is a developer example to show to how build a
|
||||
DLC with `bitcoin-s-cli` utility using the oracle
|
||||
we built in our [oracle election example](../oracle/oracle-election-example.md)
|
||||
|
||||
This example will show you to collaborate with your peer
|
||||
to create the funding transaction for your DLC.
|
||||
|
||||
The last thing we will do is close the DLC by broadcasting
|
||||
the contract execution transaction (CET) that is valid after
|
||||
the oracle broadcasts its attestations.
|
||||
|
||||
## Requirements for example
|
||||
|
||||
You need to have a fully built DLC wallet.
|
||||
You can follow [this guide](../applications/server.md#building-the-server) to do this.
|
||||
|
||||
You will also need a the `bitcoin-s-cli` command line tool to interact with the server.
|
||||
You can find how to build this [here](../applications/cli.md)
|
||||
|
||||
Since bitcoin-s is a self custodial wallet, you will need to either
|
||||
|
||||
1. [Connect your server to bitcoind](../getting-setup.md#bitcoind-backend)
|
||||
2. [Do intial block download (IBD) with blockfilters](../getting-setup.md#neutrino-node). This can take a few hours.
|
||||
|
||||
```
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server
|
||||
```
|
||||
|
||||
## US 2020 election
|
||||
|
||||
In 2020, the United States held a presidential election.
|
||||
People want to do a DLC based on the outcome.
|
||||
|
||||
### Setting up the election bet
|
||||
|
||||
#### Oracle
|
||||
The first thing you need to create a DLC is an oracle that
|
||||
is attesting to the real world event that you are interested in.
|
||||
|
||||
In this case, we will be using the oracle we setup in our
|
||||
[oracle election example](../oracle/oracle-election-example.md).
|
||||
|
||||
The announcement that this oracle produced is
|
||||
|
||||
```
|
||||
fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e
|
||||
```
|
||||
|
||||
This announcement contains all the cryptographic information
|
||||
necessary for you and your counterparty to build a DLC.
|
||||
|
||||
#### Contract
|
||||
|
||||
The next step for building a DLC is agreeing to a [contract info](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-contract_info-type).
|
||||
A contract info contains information about
|
||||
|
||||
1. The oracles that will be used by the DLC
|
||||
2. The contract payout conditions based on the oracle.
|
||||
|
||||
Up until this point all information in this example does
|
||||
NOT contain any information specific to the bitcoin network.
|
||||
|
||||
If the oracle has published their announcement to the
|
||||
Suredbits oracle explorer, you can build this
|
||||
[via the contract explorer](https://test.oracle.suredbits.com/event/8863cd80e1d37f668e27b84cbfed48541d671b4fed1462b86d547e7f13b5a9e4/contracts/new).
|
||||
|
||||
[Here](https://test.oracle.suredbits.com/contract/enum/f3650e03487941be8d3285f3eecd3689cbb9c4b49d1c6d467f92399647c45703)
|
||||
is a completed example of what we are going to build via the `bitcoin-s-cli`
|
||||
|
||||
Alice has decided that she wants to do a 100,000 sats bet.
|
||||
The amount of collateral Alice is going to contribute to the bet
|
||||
is `60,000` sats.
|
||||
|
||||
Bob, Alice's counterparty, has agreed to contribute
|
||||
`40,000` sats in collateral to the bet.
|
||||
|
||||
The next step is to create a `contractinfo` locally that represents
|
||||
this bet. We can do this with the `createcontractinfo` rpc
|
||||
|
||||
```
|
||||
./bitcoin-s-cli createcontractinfo fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e \
|
||||
100000 \
|
||||
"{\"outcomes\" : { \"Republican_win\" : 0, \"Democrat_win\" : 100000, \"other\" : 60000 }}"
|
||||
|
||||
fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e
|
||||
```
|
||||
|
||||
We can decode the encoded contract info (`fdd82efd011...`) with the `decodecontractinfo` to see what this represents
|
||||
|
||||
```
|
||||
./bitcoin-s-cli decodecontractinfo fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e
|
||||
|
||||
{
|
||||
"totalCollateral": 100000,
|
||||
"contractDescriptor": {
|
||||
"outcomes": {
|
||||
"Republican_win": 0,
|
||||
"Democrat_win": 100000,
|
||||
"other": 60000
|
||||
},
|
||||
"hex": "fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60"
|
||||
},
|
||||
"oracleInfo": {
|
||||
"announcement": {
|
||||
"announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5",
|
||||
"publicKey": "d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a",
|
||||
"event": {
|
||||
"nonces": [
|
||||
"ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14"
|
||||
],
|
||||
"maturity": "2021-02-02T00:00:00Z",
|
||||
"descriptor": {
|
||||
"outcomes": [
|
||||
"Republican_win",
|
||||
"Democrat_win",
|
||||
"other"
|
||||
],
|
||||
"hex": "fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f74686572"
|
||||
},
|
||||
"eventId": "2020-us-election"
|
||||
},
|
||||
"hex": "fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Building funding tx/dlcs with your counterparty
|
||||
|
||||
Now that the contract terms are agreed upon, the next thing you need to do is
|
||||
begin the [negotiation protocol](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#contract-negotiation) with your counterparty.
|
||||
|
||||
#### Offer
|
||||
The first thing you need to send your counterparty is an [`offer`](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#the-offer_dlc-message).
|
||||
This message contains information about the utxos you will use to fund your side of the funding transaction.
|
||||
|
||||
You can create the offer with the `createdlcoffer`. As arguments this rpc takes
|
||||
|
||||
1. contract info (what we build last step)
|
||||
2. your collateral (the amount of money YOU are putting in the DLC)
|
||||
3. fee rate (sats/vbyte)
|
||||
4. refund locktime
|
||||
|
||||
As of this writing, the current block height is `703,401`. For the sake of this example
|
||||
I'm going to pick a refund locktime 2 weeks in advance `refundLocktime=705417`
|
||||
|
||||
Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral.
|
||||
|
||||
```
|
||||
./bitcoin-s-cli createdlcoffer fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e \
|
||||
60000 \
|
||||
1 \
|
||||
705417
|
||||
a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389
|
||||
```
|
||||
|
||||
Yay! We have now created an offer (`a71a006fe...`) that we can send to our counterparty, Bob. If you would like to review
|
||||
the offer before sending it to him you can use `decodeoffer`
|
||||
|
||||
```
|
||||
./bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389
|
||||
{
|
||||
"contractFlags": "0",
|
||||
"chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000",
|
||||
"contractInfo": {
|
||||
"totalCollateral": 100000,
|
||||
"contractDescriptor": {
|
||||
"outcomes": {
|
||||
"Republican_win": 0,
|
||||
"Democrat_win": 100000,
|
||||
"other": 60000
|
||||
}
|
||||
},
|
||||
"oracleInfo": {
|
||||
"announcement": {
|
||||
"announcementSignature": "988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5",
|
||||
"publicKey": "d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a",
|
||||
"event": {
|
||||
"nonces": [
|
||||
"ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee14"
|
||||
],
|
||||
"maturity": "2021-02-02T00:00:00Z",
|
||||
"descriptor": {
|
||||
"outcomes": [
|
||||
"Republican_win",
|
||||
"Democrat_win",
|
||||
"other"
|
||||
]
|
||||
},
|
||||
"eventId": "2020-us-election"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fundingPubKey": "02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0",
|
||||
"payoutSPK": "1600141df0a84b2d2e611dd595101bfed6320143c47ebb",
|
||||
"payoutSerialId": 1.2572776984081695E19,
|
||||
"offerCollateral": 60000,
|
||||
"fundingInputs": [
|
||||
{
|
||||
"inputSerialId": 9.751703500876681E18,
|
||||
"prevTx": "02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a000000000",
|
||||
"prevTxVout": 1,
|
||||
"sequence": 4294967293,
|
||||
"maxWitnessLen": 107,
|
||||
"redeemScript": null
|
||||
}
|
||||
],
|
||||
"changeSPK": "160014eff30273b9aa3feb39fee0916a09bf2c2477df0a",
|
||||
"changeSerialId": 2059450458141810176,
|
||||
"fundOutputSerialId": 1.1508893674044221E19,
|
||||
"feeRatePerVb": 1,
|
||||
"cetLocktime": 0,
|
||||
"refundLocktime": 705417
|
||||
}
|
||||
```
|
||||
|
||||
The final thing Alice needs to give bob is here wallet's tor address. This is used to interactively
|
||||
build and verify contract execution transactions (CET). This can be done in a manual fashion, but I'm skipping
|
||||
this for the sake of brevity and better UX. Please contact me if you would like manual steps with no built in networking.
|
||||
|
||||
Alice can retrieve her dlc host address with
|
||||
```
|
||||
./bitcoin-s-cli getdlchostaddress
|
||||
v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862
|
||||
```
|
||||
|
||||
She always needs to send this Bob.
|
||||
|
||||
#### Accept
|
||||
|
||||
Once Bob has received Alice's dlc host address and the offer, and reviews the terms of the offer with `decodeoffer`, he
|
||||
can accept the offer.
|
||||
|
||||
```
|
||||
./bitcoin-s-cli acceptdlc a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e02869f5d3931620521f3eef85c0e7adf64a4db330d2dfde3aa871172274f210fe0001600141df0a84b2d2e611dd595101bfed6320143c47ebbae7b7a0db8657d43000000000000ea600001fda714fd01b3875502aad4b013d8019d02000000000102b3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0000000000fdffffffb3cb67fcadc31bfbe996d12420e2843242ebcb1885c9f81327bc9a0728ad815d0100000000fdffffff039e88010000000000220020e15f5ed79f651a30dc159b015cd26b76e26c2832d660c00365ae27aa70cf8a818ddcd80000000000160014b09f423de7c54d96bdc4173689dcbe2084165d6ee1b0e602000000001600146b34fc04227d45f792e6baddfc098cc3b74a000e0247304402203aead2ad391e573d27f3f81bab703eae6712f4c3ff6985e683f551d606925e58022042fdbc5921f569f0016bd86fbd98fa2a19792606439fec818054801d59d1297e0121036cb7209a4d6ef8af38106fc109908d7ef88f80f1265a4b392adc95ccfed3362a0247304402203b55c699d340d128c124fc21834069a3e68ba2cb4bfbf7c6d8c3feb813594ee902207b11ad746d981d49d61fa8d6a40c35de7eb2fd06ab673fa8f5d4b210467080ea012102da67b76b763ac07b9574a0f9eb87cf45a71b7b95c5446ab49845771e08dce0a00000000000000001fffffffd006b000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a1c94a347be0eddf79fb7cdd1df256b830000000000000001000abf99000ac389 v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862
|
||||
|
||||
```
|
||||
|
||||
Currently this RPC doesn't return anything, but if you look at logs you should see your funding tx broadcast.
|
||||
You can find logs at `~/.bitcoin-s/{mainnet,testnet3,regtest}/bitcoin-s.log`
|
||||
|
||||
```
|
||||
[info] 2021-10-03T21:02:52UTC INFO [DLCClient] connecting to SOCKS5 proxy localhost/127.0.0.1:49196
|
||||
[info] 2021-10-03T21:02:52UTC INFO [DLCClient] connected to SOCKS5 proxy localhost/127.0.0.1:49196
|
||||
[info] 2021-10-03T21:02:52UTC INFO [DLCClient] connecting to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion/<unresolved>:2862 via SOCKS5 localhost/127.0.0.1:49196
|
||||
[info] 2021-10-03T21:03:02UTC INFO [DLCClient] connected to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion/<unresolved>:2862 via SOCKS5 proxy localhost/127.0.0.1:49196
|
||||
[info] 2021-10-03T21:03:02UTC INFO [DLCDataHandler] Received LnMessage DLCOfferTLV
|
||||
[info] 2021-10-03T21:03:02UTC INFO [DLCWallet$DLCWalletImpl] Creating DLC Accept for tempContractId a4e127a34eb1fc998018bfc4a7e1a6943f6588d765b1e36ca6b9c7cc67b7eaa8
|
||||
[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] Spending UTXOs: 3ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b766:0
|
||||
[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] UTXO 0 details: TransactionOutput(4466999 sats,wpkh(dca26092b7540ba1c7bea286f73955a7cb247dd9))
|
||||
[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] Creating CET Sigs for a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:03UTC INFO [DLCWallet$DLCWalletImpl] Created DLCAccept for tempContractId a4e127a34eb1fc998018bfc4a7e1a6943f6588d765b1e36ca6b9c7cc67b7eaa8 with contract Id a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:04UTC INFO [DLCDataHandler] Received LnMessage DLCSignTLV
|
||||
[info] 2021-10-03T21:03:04UTC INFO [DLCWallet$DLCWalletImpl] Verifying CET Signatures for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:04UTC INFO [DLCWallet$DLCWalletImpl] CET Signatures are valid for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:04UTC INFO [DLCWallet$DLCWalletImpl] Verifying 1 funding sigs for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] DLC a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 sigs are verified and stored, ready to broadcast
|
||||
[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Created funding transaction 0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91 for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Broadcasting funding transaction 0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91 for contract a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439
|
||||
[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Adding UTXO to wallet: 91de6518fbf9eb656d9690224655049f5f21ac1c2189a142b1e0ce586989740d:2 amt=4426788 sats
|
||||
[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Successfully inserted UTXO 91de6518fbf9eb656d9690224655049f5f21ac1c2189a142b1e0ce586989740d:2 into DB
|
||||
[info] 2021-10-03T21:03:05UTC INFO [DLCWallet$DLCWalletImpl] Processing tx 0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91 for 1 DLC(s)
|
||||
```
|
||||
|
||||
You can check the state of the DLC with `getdlcs`
|
||||
|
||||
```
|
||||
./bitcoin-s-cli getdlcs
|
||||
[
|
||||
{
|
||||
"state": "Broadcasted",
|
||||
"dlcId": "2f1224d3ab1f2456d020e7777009153e2ee5db2d127b94774580e428f5a899b9",
|
||||
"isInitiator": false,
|
||||
"lastUpdated": "2021-10-03T21:03:05.539Z",
|
||||
"tempContractId": "a4e127a34eb1fc998018bfc4a7e1a6943f6588d765b1e36ca6b9c7cc67b7eaa8",
|
||||
"contractId": "a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439",
|
||||
"contractInfo": "fdd82efd011200000000000186a0fda7103b030e52657075626c6963616e5f77696e00000000000000000c44656d6f637261745f77696e00000000000186a0056f74686572000000000000ea60fda712c7fdd824c3988fabec9820690f366271c9ceac00fbec1412075f9b319bb0db1f86460519dd9c61478949f2c00c35aeb8e53a1507616072cb802891e2c189a9fa65a0493de5d3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000afdd8225f0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1460189600fdd8062400030e52657075626c6963616e5f77696e0c44656d6f637261745f77696e056f7468657210323032302d75732d656c656374696f6e",
|
||||
"contractMaturity": 704409,
|
||||
"contractTimeout": 705417,
|
||||
"feeRate": 1,
|
||||
"totalCollateral": 100000,
|
||||
"localCollateral": 40000,
|
||||
"remoteCollateral": 60000,
|
||||
"fundingTxId": "0d74896958cee0b142a189211cac215f9f0455462290966d65ebf9fb1865de91"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
You can find things like the `fundingTxId`, `state`, `dlcId`, and `contractId` from this RPC call. Since we just
|
||||
broadcast the funding transaction, the state of the DLC is `Broadcast`.
|
||||
|
||||
### Settling the DLC
|
||||
|
||||
Once the oracle has broadcast their attestations, a user can close out the DLC.
|
||||
In this case of this example, you can find the oracle
|
||||
attestations [on the oracle explorer](https://test.oracle.suredbits.com/announcement/8863cd80e1d37f668e27b84cbfed48541d671b4fed1462b86d547e7f13b5a9e4)
|
||||
|
||||
```
|
||||
fdd8688010323032302d75732d656c656374696f6ed3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1447a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd75277993590c44656d6f637261745f77696e
|
||||
```
|
||||
|
||||
We will need the contract id to close the DLC. This can be found using the `getdlcs` RPC.
|
||||
Our contract id is `a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439`
|
||||
|
||||
```
|
||||
./bitcoin-s-cli executedlc a995aeca167f1c28c2b936e5bb4d87cba061dd9147217501c3523e377fd23439 fdd8688010323032302d75732d656c656374696f6ed3b04a6d7b90c9c43c09ebe5250d583e1c3fc423219b26f6a02ec394a130000a0001ae3e30df5a203ad10ee89a909df0c8ccea4836e94e0a5d34c3cdab758fcaee1447a59ba58797e55b967aa79c89ffec67023578009c4dc1e3dee2fd75277993590c44656d6f637261745f77696e
|
||||
3cad29be34216e279d13f19153f296c4e3f8240d4a1aa04eb96a3c275478c4d1
|
||||
```
|
||||
|
||||
The thing returned is the CET's txid.
|
||||
|
||||
You've now settled your DLC :tada: :tada:
|
|
@ -0,0 +1,409 @@
|
|||
---
|
||||
id: version-1.9.2-wallet-price-example
|
||||
title: Wallet Price Example
|
||||
original_id: wallet-price-example
|
||||
---
|
||||
|
||||
This is a developer example to show to how build a
|
||||
DLC with `bitcoin-s-cli` utility using the oracle
|
||||
we built in our [oracle price example](../oracle/oracle-price-example.md)
|
||||
|
||||
This example will show you to collaborate with your peer
|
||||
to create the funding transaction for your DLC.
|
||||
|
||||
The last thing we will do is close the DLC by broadcasting
|
||||
the contract execution transaction (CET) that is valid after
|
||||
the oracle broadcasts its attestations.
|
||||
|
||||
## Requirements for example
|
||||
|
||||
You need to have a fully built DLC wallet.
|
||||
You can follow [this guide](../applications/server.md#building-the-server) to do this.
|
||||
|
||||
You will also need a the `bitcoin-s-cli` command line tool to interact with the server.
|
||||
You can find how to build this [here](../applications/cli.md)
|
||||
|
||||
Since bitcoin-s is a self custodial wallet, you will need to either
|
||||
|
||||
1. [Connect your server to bitcoind](../getting-setup.md#bitcoind-backend)
|
||||
2. [Do intial block download (IBD) with blockfilters](../getting-setup.md#neutrino-node). This can take a few hours.
|
||||
|
||||
```
|
||||
./app/server/target/universal/stage/bin/bitcoin-s-server
|
||||
```
|
||||
|
||||
## Betting on bitcoin
|
||||
|
||||
New financial markets are being built for bitcoin. Users are interested in financial
|
||||
products designed to speculate on the price of bitcoin.
|
||||
|
||||
#### Oracle
|
||||
|
||||
The first thing you need to create a DLC is an oracle that
|
||||
is attesting to the real world event that you are interested in.
|
||||
|
||||
In this case, we will be using the oracle we setup in our
|
||||
[oracle election example](../oracle/oracle-price-example.md#setting-up-the-btcusd-oracle).
|
||||
|
||||
The announcement that this oracle produced is
|
||||
|
||||
```
|
||||
fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65
|
||||
```
|
||||
|
||||
This announcement contains all the cryptographic information
|
||||
necessary for you and your counterparty to build a DLC.
|
||||
|
||||
#### Contract
|
||||
|
||||
The next step for building a DLC is agreeing to a [contract info](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-contract_info-type).
|
||||
A contract info contains information about
|
||||
|
||||
1. The oracles that will be used by the DLC
|
||||
2. The contract payout conditions based on the oracle.
|
||||
|
||||
Up until this point all information in this example does
|
||||
NOT contain any information specific to the bitcoin network.
|
||||
|
||||
If the oracle has published their announcement to the
|
||||
Suredbits oracle explorer, you can build this
|
||||
[via the contract explorer](https://test.oracle.suredbits.com/event/362ae482860fc93bac5cbcca3f1f0e49b3c94eac92224a008bd81ef81292f43a/contracts/new).
|
||||
|
||||
[Here](https://test.oracle.suredbits.com/contract/numeric/d4d4df2892fb2cfd2e8f030f0e69a568e19668b5d355e7713f69853db09a4c33)
|
||||
is a completed example of what we are going to build via the `bitcoin-s-cli`
|
||||
|
||||
Alice has decided that she wants to do a 1 bitcoin bet.
|
||||
The amount of collateral Alice is going to contribute to the bet
|
||||
is `50,000` sats.
|
||||
|
||||
Bob, Alice's counterparty, has agreed to contribute
|
||||
`50,000` sats in collateral to the bet.
|
||||
|
||||
The next step is to create a `contractinfo` [via the contract explorer hosted by Suredbits](https://test.oracle.suredbits.com/contract/numeric/d4d4df2892fb2cfd2e8f030f0e69a568e19668b5d355e7713f69853db09a4c33)
|
||||
or locally that represents this bet.
|
||||
|
||||
These next instructions are for if you decide to build it locally.
|
||||
|
||||
We can do this with the `createcontractinfo` rpc
|
||||
|
||||
```
|
||||
./bitcoin-s-cli createcontractinfo fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \
|
||||
100000 \
|
||||
"[{\"outcome\":0,\"payout\":0,\"extraPrecision\":0,\"isEndpoint\":true}, \
|
||||
{\"outcome\":40000,\"payout\":0,\"extraPrecision\":0,\"isEndpoint\":true}, \
|
||||
{\"outcome\":42500,\"payout\":50000,\"extraPrecision\":0,\"isEndpoint\":true}, \
|
||||
{\"outcome\":45000,\"payout\":100000,\"extraPrecision\":0,\"isEndpoint\":true}, \
|
||||
{\"outcome\":131071,\"payout\":100000,\"extraPrecision\":0,\"isEndpoint\":true}]"
|
||||
|
||||
fdd82efd031f00000000000186a0fda7204e0011fda72642000400000000fda728020000fd9c40000000fda728020000fda604fdc3500000fda728020000fdafc8fe000186a00000fda728020000fe0001fffffe000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65
|
||||
```
|
||||
|
||||
The `fdd824fd02b96...` is the oracle announcement, the `100000` is the total collateral in the DLC
|
||||
and the final json datstructure is the points on the payout curve. The x-axis is `outcome`
|
||||
and the y axis is `payout`.
|
||||
|
||||
You can decode this contract info with `decodecontractinfo`
|
||||
|
||||
```
|
||||
./bitcoin-s-cli decodecontractinfo fdd82efd031f00000000000186a0fda7204e0011fda72642000400000000fda728020000fd9c40000000fda728020000fda604fdc3500000fda728020000fdafc8fe000186a00000fda728020000fe0001fffffe000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65
|
||||
{
|
||||
"totalCollateral": 100000,
|
||||
"contractDescriptor": {
|
||||
"numDigits": 17,
|
||||
"payoutFunction": {
|
||||
"points": [
|
||||
{
|
||||
"outcome": 0,
|
||||
"payout": 0,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 40000,
|
||||
"payout": 0,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 42500,
|
||||
"payout": 50000,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 45000,
|
||||
"payout": 100000,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 131071,
|
||||
"payout": 100000,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"roundingIntervals": {
|
||||
"intervals": [
|
||||
|
||||
]
|
||||
},
|
||||
"hex": "fda7204e0011fda72642000400000000fda728020000fd9c40000000fda728020000fda604fdc3500000fda728020000fdafc8fe000186a00000fda728020000fe0001fffffe000186a00000fda724020000"
|
||||
},
|
||||
"oracleInfo": {
|
||||
"announcement": {
|
||||
"announcementSignature": "659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e5703",
|
||||
"publicKey": "0574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949",
|
||||
"event": {
|
||||
"nonces": [
|
||||
"4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6",
|
||||
"588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274",
|
||||
"a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd",
|
||||
"166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e",
|
||||
"88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2",
|
||||
"238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88",
|
||||
"a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5",
|
||||
"719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433",
|
||||
"7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3",
|
||||
"ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f",
|
||||
"853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d",
|
||||
"1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84",
|
||||
"cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c",
|
||||
"104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab6669983",
|
||||
"2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968",
|
||||
"aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82",
|
||||
"ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d"
|
||||
],
|
||||
"maturity": "2021-02-04T00:00:00Z",
|
||||
"descriptor": {
|
||||
"base": 2,
|
||||
"isSigned": false,
|
||||
"unit": "BTC/USD",
|
||||
"precision": 0,
|
||||
"hex": "fdd80a11000200074254432f555344000000000011"
|
||||
},
|
||||
"eventId": "bitcoin-s-price-example"
|
||||
},
|
||||
"hex": "fdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Building funding tx/dlcs with your counterparty
|
||||
|
||||
Now that the contract terms are agreed upon, the next thing you need to do is
|
||||
begin the [negotiation protocol](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#contract-negotiation) with your counterparty.
|
||||
|
||||
#### Offer
|
||||
|
||||
The first thing you need to send your counterparty is an [`offer`](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#the-offer_dlc-message).
|
||||
This message contains information about the utxos you will use to fund your side of the funding transaction.
|
||||
|
||||
You can create the offer with the `createdlcoffer`. As arguments this rpc takes
|
||||
|
||||
1. contract info (what we build last step)
|
||||
2. your collateral (the amount of money YOU are putting in the DLC)
|
||||
3. fee rate (sats/vbyte)
|
||||
4. refund locktime
|
||||
|
||||
As of this writing, the current block height is `705161` . For the sake of this example
|
||||
I'm going to pick a refund locktime 2 weeks in advance `refundLocktime=707177`
|
||||
|
||||
Note: this RPC will fail if you don't have enough funds in your wallet to fund your collateral.
|
||||
|
||||
```
|
||||
./bitcoin-s-cli createdlcoffer fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65 \
|
||||
50000 \
|
||||
1 \
|
||||
> 707177 \
|
||||
a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69
|
||||
```
|
||||
|
||||
You can decode the offer above with `decodeoffer`
|
||||
|
||||
```
|
||||
./bitcoin-s-cli decodeoffer a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69
|
||||
{
|
||||
"contractFlags": "0",
|
||||
"chainHash": "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000",
|
||||
"contractInfo": {
|
||||
"totalCollateral": 100000,
|
||||
"contractDescriptor": {
|
||||
"numDigits": 17,
|
||||
"payoutFunction": {
|
||||
"points": [
|
||||
{
|
||||
"outcome": 0,
|
||||
"payout": 0,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 40000,
|
||||
"payout": 0,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 42500,
|
||||
"payout": 50000,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 45000,
|
||||
"payout": 100000,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
},
|
||||
{
|
||||
"outcome": 131071,
|
||||
"payout": 100000,
|
||||
"extraPrecision": 0,
|
||||
"isEndpoint": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"roundingIntervals": {
|
||||
"intervals": []
|
||||
}
|
||||
},
|
||||
"oracleInfo": {
|
||||
"announcement": {
|
||||
"announcementSignature": "659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e5703",
|
||||
"publicKey": "0574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949",
|
||||
"event": {
|
||||
"nonces": [
|
||||
"4762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6",
|
||||
"588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274",
|
||||
"a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd",
|
||||
"166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e",
|
||||
"88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2",
|
||||
"238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88",
|
||||
"a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5",
|
||||
"719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e6433",
|
||||
"7d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3",
|
||||
"ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f",
|
||||
"853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d",
|
||||
"1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84",
|
||||
"cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c",
|
||||
"104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab6669983",
|
||||
"2ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968",
|
||||
"aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82",
|
||||
"ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d"
|
||||
],
|
||||
"maturity": "2021-02-04T00:00:00Z",
|
||||
"descriptor": {
|
||||
"base": 2,
|
||||
"isSigned": false,
|
||||
"unit": "BTC/USD",
|
||||
"precision": 0
|
||||
},
|
||||
"eventId": "bitcoin-s-price-example"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fundingPubKey": "03a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33",
|
||||
"payoutSPK": "1600148cd33b6fadc74aaca3982d3fd1891b1100a01e99",
|
||||
"payoutSerialId": 7520084828858968064,
|
||||
"offerCollateral": 50000,
|
||||
"fundingInputs": [
|
||||
{
|
||||
"inputSerialId": 3740391543456242688,
|
||||
"prevTx": "020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e83200000000",
|
||||
"prevTxVout": 0,
|
||||
"sequence": 4294967293,
|
||||
"maxWitnessLen": 107,
|
||||
"redeemScript": null
|
||||
}
|
||||
],
|
||||
"changeSPK": "16001404a16b09c5eba2e29899d2eaf5e9dde374be4940",
|
||||
"changeSerialId": 3404283908717475840,
|
||||
"fundOutputSerialId": 6109310038405377024,
|
||||
"feeRatePerVb": 1,
|
||||
"cetLocktime": 0,
|
||||
"refundLocktime": 707177
|
||||
}
|
||||
```
|
||||
|
||||
Now what Alice needs to send Bob her
|
||||
|
||||
1. Offer
|
||||
2. Tor address
|
||||
|
||||
She can retrieve her tor address with
|
||||
|
||||
```
|
||||
./bitcoin-s-cli getdlchostaddress
|
||||
v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862
|
||||
```
|
||||
|
||||
#### Accept
|
||||
|
||||
Once Bob has received Alice's dlc host address and the offer, and reviews the terms of the offer with `decodeoffer`, he
|
||||
can accept the offer.
|
||||
|
||||
```
|
||||
./bitcoin-s-cli acceptdlc a71a006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c6503a63505d00a2f927904f9c7d3cd28b59cb105b8d028fc1b715ef243351cea0f33001600148cd33b6fadc74aaca3982d3fd1891b1100a01e99685cb54f08f168cf000000000000c3500001fda714fd01b333e88a4a94959b16019d020000000001023ef93b35f692ce8f7ee0cfeb034941dec751fd9237624482d447964cbca1b7660000000000fdffffff787320985c52d762a56cdc5e64ef1155f0ccc722e3f51bd164406261dbc0e3ab0100000000fdffffff035af1d70000000000160014eff30273b9aa3feb39fee0916a09bf2c2477df0a4a87010000000000220020740aa2449461fd922c136ac68cd954773896276f6fc1b3b98821bac43729f012248c4300000000001600147532253f570665ff9af4b53bcac49351f8236c8402473044022027fccc6f4f796465c36261d02db821a38253e44d968c9c02ae366f743cb51bf802202eedb11a6dd006e7c1b7aefb6a5f0d729f958ccc0f88887c73d756533958d9ac01210203772fc0e7d0550414e00254af8ef148999bff47a0ceb31f44b45d7f46b4d7ec0247304402207d008545f772aadc1a2c6a632140c0c720ea0371fcce8863a7fedcb7222b0f8102203f86e0ee14ac1b9b113294fc00b81f989e064441a35e86cb1d67075c7ab4029101210360d0f354faab35e3e2ee50a39059a72ba923162ca3f1ddb75a617de19447e8320000000000000000fffffffd006b00000016001404a16b09c5eba2e29899d2eaf5e9dde374be49402f3e722da5aef87f54c8a11c85e16ac90000000000000001000ac679000aca69 v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862
|
||||
|
||||
```
|
||||
|
||||
Currently this RPC doesn't return anything, but if you look at logs you should see your funding tx broadcast.
|
||||
You can find logs at `~/.bitcoin-s/{mainnet,testnet3,regtest}/bitcoin-s.log`
|
||||
|
||||
```
|
||||
[info] 2021-10-15T21:21:11UTC INFO [DLCClient] connecting to SOCKS5 proxy localhost/127.0.0.1:65396
|
||||
[info] 2021-10-15T21:21:11UTC INFO [DLCClient] connected to SOCKS5 proxy localhost/127.0.0.1:65396
|
||||
[info] 2021-10-15T21:21:11UTC INFO [DLCClient] connecting to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 via SOCKS5 localhost/127.0.0.1:65396
|
||||
[info] 2021-10-15T21:21:48UTC INFO [DLCClient] connected to v573gl64h5zik544qvi725vxliiwwpsedarsziidp254u3cfnxlp6zqd.onion:2862 via SOCKS5 proxy localhost/127.0.0.1:65396
|
||||
[info] 2021-10-15T21:21:48UTC INFO [DLCDataHandler] Received LnMessage DLCOfferTLV
|
||||
[info] 2021-10-15T21:21:48UTC INFO [DLCWallet$DLCWalletImpl] Initializing DLC from received offer with tempContractId acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e
|
||||
[info] 2021-10-15T21:21:48UTC INFO [HikariDataSource] bitcoin-s.dlc.db - Starting...
|
||||
[info] 2021-10-15T21:21:48UTC INFO [HikariDataSource] bitcoin-s.dlc.db - Start completed.
|
||||
[info] 2021-10-15T21:21:48UTC INFO [DLCWallet$DLCWalletImpl] Creating DLC Accept for tempContractId acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e
|
||||
[info] 2021-10-15T21:21:49UTC INFO [DLCWallet$DLCWalletImpl] Spending UTXOs: 91de6518fbf9eb656d9690224655049f5f21ac1c2189a142b1e0ce586989740d:2
|
||||
[info] 2021-10-15T21:21:49UTC INFO [DLCWallet$DLCWalletImpl] UTXO 0 details: TransactionOutput(4426788 sats,wpkh(7532253f570665ff9af4b53bcac49351f8236c84))
|
||||
[info] 2021-10-15T21:21:49UTC INFO [DLCWallet$DLCWalletImpl] Creating CET Sigs for fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:21:50UTC INFO [DLCWallet$DLCWalletImpl] Created DLCAccept for tempContractId acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e with contract Id fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:22:07UTC INFO [DLCDataHandler] Received LnMessage DLCSignTLV
|
||||
[info] 2021-10-15T21:22:07UTC INFO [DLCWallet$DLCWalletImpl] Verifying CET Signatures for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:22:09UTC INFO [DLCWallet$DLCWalletImpl] CET Signatures are valid for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:22:09UTC INFO [DLCWallet$DLCWalletImpl] Verifying 1 funding sigs for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:22:11UTC INFO [DLCWallet$DLCWalletImpl] DLC fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701 sigs are verified and stored, ready to broadcast
|
||||
[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Created funding transaction 5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Broadcasting funding transaction 5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f for contract fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701
|
||||
[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Adding UTXO to wallet: 6f61f256bceb3a3d987b29246c012090943365d0b0eb82c88d62ca0f8ea89650:2 amt=4376577 sats
|
||||
[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Successfully inserted UTXO 6f61f256bceb3a3d987b29246c012090943365d0b0eb82c88d62ca0f8ea89650:2 into DB
|
||||
[info] 2021-10-15T21:22:12UTC INFO [DLCWallet$DLCWalletImpl] Processing tx 5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f for 1 DLC(s)
|
||||
```
|
||||
|
||||
You can check the state of the DLC with `getdlcs`
|
||||
|
||||
```
|
||||
./bitcoin-s-cli getdlcs
|
||||
[
|
||||
{
|
||||
"state": "Broadcasted",
|
||||
"dlcId": "543249d7c34014a774810d3633fb7d19f339fbcd4e88ceccad7018fa7b611706",
|
||||
"isInitiator": false,
|
||||
"lastUpdated": "2021-10-15T21:22:12.149Z",
|
||||
"tempContractId": "acdeaf6a46f3dab8be37e59a3684183cdbfd4e9fbc84a09fc420d67c1334466e",
|
||||
"contractId": "fc4807e44939b83576b50e2ae6e12ba84bdd4ff398addb07f91a3dc045c62701",
|
||||
"contractInfo": "fdd82efd032500000000000186a0fda720540011fda72648000501000000000000000000000001fd9c400000000000000000000001fda604000000000000c350000001fdafc800000000000186a0000001fe0001ffff00000000000186a00000fda724020000fda712fd02bffdd824fd02b9659e890eef1b223ba45c9993f88c7997859302fd5510ac23f4cac0d4ee8232a77ecbdf50c07f093794370e6a506a836f6b0fb54b45f1fb662e1307166d2e57030574f77305826939fa9124d19bfa8a8b2f00f000586b8c58c79ee8b77969a949fdd822fd025300114762c188048a953803f0edeeeb68c69e6cdc1d371ba8d517003accfe05afc4d6588c3ea326512bc66c26a841adffa68330b8c723da442792e731fb19fda94274a7766bb48e520f118c100bbe62dc3806a8d05a63d92e23683a04b0b8c24148cd166585a6b33b995b3d6c083523a8435b156c05100d88f449f4754310d5574d5e88aad09af1b8ba942cfd305e728044ec6360d847254453ec05b1b518a36660e2238360e02f3a004663a7f3a3534973d8b66a2646c1386779aa820672b6361b88a8696395c0add87840b460dfd8a8c0d520017efc6bf58267d4c9d2a225c5d0e5719068a7dda5d630d7432239b6c9d921d5f3842b584503460ca52612ac2e64337d299513690372e8f4770eb8a28080e8d7c29920ca32af470d65d6f916ee81e3ac15ce02684ba6d2522a9ffea1de7e202b4b699ef7ec4f089dda07f3de5b7d1f853b2c56471999be4efca82674a651c80f047ba3a2b9e6f9999f0cd4062c533d1ae29cab2a5e33cbe98728b7b4271c67f7c5cd6e12e39128b9971e08496cbd84cfa99c77c88867d33e73acef37022ba4422a5221776991d45416db71fb54bc6c104f6a8e50e8905161709215104a7e7b97e866f32cf43233ffd615cab66699832ec607cf59c85a7f56fa957aa5f5d7ec9f46d84d5d4b777122d41ad76c6f4968aeedca243f2030d4f502e58f4181130e9afb75309ac21637bcfd0717528bfb82ffe1b6c9fadee6ba70357210990539184bcc913a0ec65837a736733a2fb6172d601b3900fdd80a11000200074254432f55534400000000001117626974636f696e2d732d70726963652d6578616d706c65",
|
||||
"contractMaturity": 706169,
|
||||
"contractTimeout": 707177,
|
||||
"feeRate": 1,
|
||||
"totalCollateral": 100000,
|
||||
"localCollateral": 50000,
|
||||
"remoteCollateral": 50000,
|
||||
"fundingTxId": "5096a88e0fca628dc882ebb0d06533949020016c24297b983d3aebbc56f2616f"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
You can find things like the `fundingTxId`, `state`, `dlcId`, and `contractId` from this RPC call. Since we just
|
||||
broadcast the funding transaction, the state of the DLC is `Broadcast`.
|
|
@ -1,4 +1,5 @@
|
|||
[
|
||||
"1.9.2",
|
||||
"1.9.1",
|
||||
"1.9.0",
|
||||
"1.8.0",
|
||||
|
|
Loading…
Add table
Reference in a new issue