Revert "GitBook: [master] 7 pages modified"

This reverts commit 2bb48fd534.
This commit is contained in:
Olaoluwa Osuntokun 2020-10-29 18:25:14 -07:00
parent 2bb48fd534
commit 08fd1a3a6e
7 changed files with 372 additions and 224 deletions

View file

@ -1,55 +1,2 @@
# Introduction
Lightning Pool is a non-custodial, peer-to-peer marketplace that allows node operators that need inbound liquidity to pay node operators with available capital to open channels in their direction while retaining full custody of their funds. Pools first product is a Lightning Channel Lease - an inbound channel with a pre-agreed duration.
Efficient capital allocation is one of the most widely felt pain points when using the Lightning Network. Existing node operators do not have access to pricing signals to help determine where in the network their outbound liquidity should be allocated, and new node operators have no way to signal that they need new inbound liquidity. Lightning Pool brings these two sides together into a single market while allowing them to maintain custody of their funds.
Checkout our [documentation]() to learn more.
## How it works
Lightning Pool is a non-custodial auction for liquidity where bids are kept private and trades clear periodically. Key aspects of Pool include:
* **Periodic clearing** - Market does not clear continuously, instead, it clears every block \(or after multiple blocks, if there are no bids that match with existing asks\).
* **Non-custodial** - Clients maintain an on-chain account that is a timelocked, 2-of-2 multisig with the auctioneer. These funds are fully in the users control at all times.
* **Sealed-bid** - All orders are submitted off-chain to the auctioneer, so bidders dont have visibility into the bids of other participants
* **Uniform clearing price** - All participants in a batch clear at the same price. If your ask is for 2% annualized interest, you will receive >=2%. If you bid 5%, you will pay <=5%.
* **Batched execution** - Due to the account structure, the auctioneer is able to batch all completed orders into a single transaction, greatly reducing individual chain fees.
## Installation
Download the latest binaries from the [releases](https://github.com/lightninglabs/pool/releases) page.
## LND
Note that LiT requires `lnd` to be built with **all of its subservers** and requires running at least `v0.11.1`. Download the latest [official release binary](https://github.com/lightningnetwork/lnd/releases/latest) or build `lnd` from source by following the [installation instructions](https://github.com/lightningnetwork/lnd/blob/master/docs/INSTALL.md). If you choose to build `lnd` from source, use the following command to enable all the relevant subservers:
```text
make install tags="signrpc walletrpc chainrpc invoicesrpc"
```
## Usage
Read our [getting started guide]() to learn more about how to use Pool.
## Troubleshooting
[Join us on Slack](https://lightning.engineering/slack.html) and we'd be happy to help in any way we can. In the meantime please see our [FAQs]().
## Build from source
If youd prefer to compile from source code, youll need at least `go 1.14` and `make`.
Run the following commands to download the code, compile and install Pool:
```text
git clone https://github.com/lightninglabs/pool
cd pool make install
```
This will install the binaries into your `$GOPATH/bin` directory.
## Compatibility
Lightning Pool requires `lnd` version `0.11.1-beta` or higher

View file

@ -1,6 +1,7 @@
# Table of contents
* [Introduction](README.md)
* [Lightning Pool: A Non-Custodial Channel Lease Marketplace](lightning_pool.md)
* [Overview](overview.md)
* [Installation](install.md)
* [Accounts](accounts.md)

View file

@ -1,43 +1,100 @@
# Batch Execution
Now that we have orders submitted, how does the rest of the auction actually work? As mentioned above, Pool conducts a _discrete_ batch auction every 10 minutes. This is distinct from regular continuous exchanges in that orders are only cleared every 10 minutes. Orders are also sealed-bid, meaning that other traders in the venue are unable to see what others have bid. On top of this, we utilize a uniform-clearing price algorithm to give all traders in the batch the _same_ interest rate. This is the same mechanism used by the U.S Treasury for its bonds, and is intended to promote fairness as your order will only be matched with a price better than your initial ask/bid.
Now that we have orders submitted, how does the rest of the auction actually
work? As mentioned above, Pool conducts a _discrete_ batch auction every 10
minutes. This is distinct from regular continuous exchanges in that orders are
only cleared every 10 minutes. Orders are also sealed-bid, meaning that other
traders in the venue are unable to see what others have bid. On top of this, we
utilize a uniform-clearing price algorithm to give all traders in the batch the
_same_ interest rate. This is the same mechanism used by the U.S Treasury for
its bonds, and is intended to promote fairness as your order will only be
matched with a price better than your initial ask/bid.
Note that it's possible that after the 10 minutes interval has passed a market can't be made \(supply and demand didn't cross\). In this case, nothing happens, and we just wait for the next batch to come across.
Note that it's possible that after the 10 minutes interval has passed a market
can't be made \(supply and demand didn't cross\). In this case, nothing
happens, and we just wait for the next batch to come across.
### Matchmaking
The first stage in batch execution is the matchmaking that is done by the auctioneer. Before actual matchmaking is performed, the auctioneer looks at the current fee climate and decides what fee rate should be used for the final Batch Execution Transaction, in order for the transaction to confirm in a timely manner. All orders that have their `max_batch_fee_rate` set to a value lower than the chosen fee rate are ignored from the auction this time around, but will be reconsidered if the fee climate changes before the next auction. This allows traders with a low time preference to submit orders that will stay around on the order book and only be considered for matchmaking in times of low chain fees.
The first stage in batch execution is the matchmaking that is done by the
auctioneer. Before actual matchmaking is performed, the auctioneer looks at the
current fee climate and decides what fee rate should be used for the final
Batch Execution Transaction, in order for the transaction to confirm in a
timely manner. All orders that have their `max_batch_fee_rate` set to a value
lower than the chosen fee rate are ignored from the auction this time around,
but will be reconsidered if the fee climate changes before the next auction.
This allows traders with a low time preference to submit orders that will stay
around on the order book and only be considered for matchmaking in times of low
chain fees.
Now that the transaction fee rate has been chosen, all orders still on the order book are considered, and the auctioneer matches asks with bids that pay at least the desired rate. The unsigned Batch Execution Transaction \(BET\) is assembled and presented to all traders that had their orders matched, along with information about the node they matched with.
Now that the transaction fee rate has been chosen, all orders still on the
order book are considered, and the auctioneer matches asks with bids that pay
at least the desired rate. The unsigned Batch Execution Transaction (BET) is
assembled and presented to all traders that had their orders matched, along
with information about the node they matched with.
### Batch Signing
When the trader's client receives a notification about a batch that is under execution, it checks that every part of the BET that affects the trader meets its requirements. This includes checking that the premium paid to the maker matches the batch clearing price, and that the chain fee deducted from the trader's account doesn't violate the max fee rate the trader agreed to.
When the trader's client receives a notification about a batch that is under
execution, it checks that every part of the BET that affects the trader meets
its requirements. This includes checking that the premium paid to the maker
matches the batch clearing price, and that the chain fee deducted from the
trader's account doesn't violate the max fee rate the trader agreed to.
Each match the trader was part of results in a channel output on the BET, and the trader will also ensure this is well formed, and of the expected amount. When that has been verified, the trader connects to the node on the other side of the match, and starts the channel opening process with the channel peer. Technically this is done by setting up a _funding shim_ with the backing `lnd` node, which prepares `lnd` for a funding transaction setting up a channel with the given parameters to be broadcast.
Each match the trader was part of results in a channel output on the BET, and
the trader will also ensure this is well formed, and of the expected amount.
When that has been verified, the trader connects to the node on the other side
of the match, and starts the channel opening process with the channel peer.
Technically this is done by setting up a _funding shim_ with the backing `lnd`
node, which prepares `lnd` for a funding transaction setting up a channel with
the given parameters to be broadcast.
Only when all these checks are satisfactory and the channel funding shim has been successfully set up, the trader signs its input to the batch transaction and responds to the auctioneer. This ensures the trader is always _fully in custody of its own funds_, and never signs a transaction that would send the funds to an output it doesn't control.
Only when all these checks are satisfactory and the channel funding shim has
been successfully set up, the trader signs its input to the batch transaction
and responds to the auctioneer. This ensures the trader is always _fully in
custody of its own funds_, and never signs a transaction that would send the
funds to an output it doesn't control.
Note that the trader can reject signing the batch for any reason, even when the BET is well formed. For instance, connecting to the channel peer can fail, resulting in the channel not being ready to be funded. The trader will reject this match, and matchmaking can start over, making sure the trader won't be matched with this channel peer again.
Note that the trader can reject signing the batch for any reason, even when the
BET is well formed. For instance, connecting to the channel peer can fail,
resulting in the channel not being ready to be funded. The trader will reject
this match, and matchmaking can start over, making sure the trader won't be
matched with this channel peer again.
### Batch Publication
When all participating traders have signed their inputs in the Batch Execution Transaction, the auctioneer can sign the final input and broadcast the transaction. This transaction can be large, and serve as the funding transaction for potentially hundres of channels! The participating traders only pay chain fees for their inputs and outputs in the transaction, so everybody is saving substantially on fees compared to individually funding channels.
When all participating traders have signed their inputs in the Batch Execution
Transaction, the auctioneer can sign the final input and broadcast the
transaction. This transaction can be large, and serve as the funding
transaction for potentially hundres of channels! The participating traders only
pay chain fees for their inputs and outputs in the transaction, so everybody is
saving substantially on fees compared to individually funding channels.
## Batched Uniform-Price Clearing
To illustrate how the uniform price clearing works consider the following example. Let's say I want to buy 100 million satoshis \(1 BTC, 1000 units\), for 2 weeks \(2016 blocks\) at a price of 5% \(using high numbers to make it easy to follow\). However, the _market clearing price_ \(where the supply+demand curves cross\) is actually 1%. In this case I bid _more_ than the market clearing price, but end up paying that price, as it's the best price that was possible in that market.
To illustrate how the uniform price clearing works consider the following
example. Let's say I want to buy 100 million satoshis \(1 BTC, 1000 units\),
for 2 weeks \(2016 blocks\) at a price of 5% \(using high numbers to make it
easy to follow\). However, the _market clearing price_ \(where the
supply+demand curves cross\) is actually 1%. In this case I bid _more_ than the
market clearing price, but end up paying that price, as it's the best price
that was possible in that market.
A simple rule of thumb for bids and asks is as follows:
* When I submit a bid, I'll either pay that amount or less.
* When I submit an ask, I'll either receive that amount or more.
All orders in a batch are executed in a _single_ on-chain transaction. This allows for thousands of channels to be bought/sold atomically in a single block. We call the transaction that executes the orders the Batch Execution Transaction.
All orders in a batch are executed in a _single_ on-chain transaction. This
allows for thousands of channels to be bought/sold atomically in a single
block. We call the transaction that executes the orders the Batch Execution
Transaction.
The `pool auction` sub-command houses a number of useful commands to explore the past batches, and examine the current auction parameters.
The `pool auction` sub-command houses a number of useful commands to explore
the past batches, and examine the current auction parameters.
One can browse the latest cleared batch using the `pool auction snapshot` command:
One can browse the latest cleared batch using the `pool auction snapshot`
command:
```text
🏔 pool auction snapshot
@ -70,11 +127,19 @@ One can browse the latest cleared batch using the `pool auction snapshot` comman
}
```
Here we see a batch where a single order was matched, at a clearing rate of `1636`, with a single channel being purchased with a lifetime of `2016` blocks, or roughly two weeks.
Here we see a batch where a single order was matched, at a clearing rate of
`1636`, with a single channel being purchased with a lifetime of `2016` blocks,
or roughly two weeks.
Note that the `pool auction snapshot` command can be used to determine the past marker clearing price, which can be useful when deciding what your bid/ask should be. There's no explicit "market buy" function, but submitting a bid/ask at a similar `clearing_price_rate` to the historical one should put you close to where the demand in the market is.
Note that the `pool auction snapshot` command can be used to determine the past
marker clearing price, which can be useful when deciding what your bid/ask
should be. There's no explicit "market buy" function, but submitting a bid/ask
at a similar `clearing_price_rate` to the historical one should put you close
to where the demand in the market is.
The command also accept a target `batch_id` as well. Here we can use the `prev_batch_id` to examine the _prior_ batch, similar to traversing a link-listed/blockchain:
The command also accept a target `batch_id` as well. Here we can use the
`prev_batch_id` to examine the _prior_ batch, similar to traversing a
link-listed/blockchain:
```text
🏔 pool auction snapshot --batch_id=03687baa3c7414e800ddba37edacb3281999739303b7290a69bd457f428ecd9b2c
@ -82,7 +147,9 @@ The command also accept a target `batch_id` as well. Here we can use the `prev_b
## Fees
There are various fees paid and accumulated during a successful batch execution. The easiest way to get an overview of the total impact of fees on ones account is to run
There are various fees paid and accumulated during a successful batch
execution. The easiest way to get an overview of the total impact of fees on
ones account is to run
```text
🏔 pool auction leases
@ -127,9 +194,18 @@ There are various fees paid and accumulated during a successful batch execution.
}
```
Here you can see a summary of all matches you've been part of and that resulted in a channel being opened. In the first example the trader sold a 1,200,000 sat channel and got paid a premium of 59,998 sats for this liquidity. To be part of this batch, the trader paid an execution fee of 1201 sats, and a chain fee of 165 sats, netting 59998-1201-165 = 58632 sats that got paid to its account.
Here you can see a summary of all matches you've been part of and that resulted
in a channel being opened. In the first example the trader sold a 1,200,000 sat
channel and got paid a premium of 59,998 sats for this liquidity. To be part of
this batch, the trader paid an execution fee of 1201 sats, and a chain fee of
165 sats, netting 59998-1201-165 = 58632 sats that got paid to its account.
In the last example in the list above, the trader this time around bought a channel of 1,200,000 sats, and paid a premium of 11999 to the seller. Also this time around the trader paid an execution fee and chain fee, resulting in a total cost of 11999+1201+165 = 13365 sats.
In the last example in the list above, the trader this time around bought a
channel of 1,200,000 sats, and paid a premium of 11999 to the seller. Also this
time around the trader paid an execution fee and chain fee, resulting in a
total cost of 11999+1201+165 = 13365 sats.
Finally, a total tally of fees earned and paid is given. The command takes optional account and batch id arguments in case you want to filter the leases returned.
Finally, a total tally of fees earned and paid is given. The command takes
optional account and batch id arguments in case you want to filter the leases
returned.

View file

@ -33,11 +33,11 @@ You can choose the chain fee rate for these operations.
### How will I know if my order was fulfilled?
Watch the logs. Pull the order snapshot locally. Watch your account balance. Pool orders list.
Watch the logs. Pull the order snapshot locally. Watch your account balance. Pool orders list.
### How soon after my order is filled will the seller open a channel to me?
A channel will be opened as soon as the batch transaction has received N confirmations.
A channel will be opened as soon as the batch transaction has received N confirmations.
If the sellers node is offline when the batch clears, \_\_\_\_
@ -47,7 +47,7 @@ No, you cannot choose who you peer with. You will peer with any partner who is a
### Who earns the routing fees from the channel that is opened with me?
The seller earns the routing fees. You can also earn fees if that new channel is used by a routing node.
The seller earns the routing fees. You can also earn fees if that new channel is used by a routing node.
### Can I specify the maximum fee rate of a peer Im buying liquidity from?
@ -71,7 +71,7 @@ In the future this node may be removed from the market by market participant sel
### What happens if the lender force closes a channel before the maturity date?
If the lender force closes they will be banned from the market. This will not be possible in future versions.
If the lender force closes they will be banned from the market. This will not be possible in future versions.
### What is the minimum purchase time for a channel?
@ -139,7 +139,7 @@ This is necessary so that users can recover funds in the event we disappear.
### What do I do if my account expires?
Currently you will need to close your account and then re-open your account. In the future you will be able to renew your account as part of a batch will be the most cost efficient way of opening an account.
Currently you will need to close your account and then re-open your account. In the future you will be able to renew your account as part of a batch will be the most cost efficient way of opening an account.
## Technical questions
@ -166,7 +166,9 @@ accounts leases
### Do I need to keep `poold` running the whole time?
To participate in an auction, the `poold` trader daemon needs to be in constant communication with the auction server to validate and then sign potential batch transactions.
Once all orders are in a final state \(either fully matched or canceled\), the trader daemon can be safely shut down.
To participate in an auction, the `poold` trader daemon needs to be in constant
communication with the auction server to validate and then sign potential batch
transactions.
Once all orders are in a final state (either fully matched or canceled), the
trader daemon can be safely shut down.

View file

@ -1,28 +1,40 @@
# Installation
## Installation
Lightning Pool is built very similarly to
[Lightning Loop](https://github.com/lightninglabs/loop): There is a process that
is constantly running in the background, called the trader daemon (`poold`) and
a command line tool to interact with the daemon, called just `pool`.
Lightning Pool is built very similarly to [Lightning Loop](https://github.com/lightninglabs/loop): There is a process that is constantly running in the background, called the trader daemon \(`poold`\) and a command line tool to interact with the daemon, called just `pool`.
The `poold` trader daemon can be run either as a standalone binary connected to
a compatible `lnd` node or integrated into
[Lightning Terminal (LiT)](https://github.com/lightninglabs/lightning-terminal).
The `poold` trader daemon can be run either as a standalone binary connected to a compatible `lnd` node or integrated into [Lightning Terminal \(LiT\)](https://github.com/lightninglabs/lightning-terminal).
## Downloading the standalone binaries
### Downloading the standalone binaries
The latest official release binaries can be [downloaded from the GitHub
releases page](https://github.com/lightninglabs/pool/releases).
The latest official release binaries can be [downloaded from the GitHub releases page](https://github.com/lightninglabs/pool/releases).
## Downloading as part of Lightning Terminal (LiT)
### Downloading as part of Lightning Terminal \(LiT\)
To run `poold` integrated into the Lightning Terminal, download [the latest
release of LiT](https://github.com/lightninglabs/lightning-terminal/releases)
and follow
[the installation instructions of LiT](https://github.com/lightninglabs/lightning-terminal#execution)
To run `poold` integrated into the Lightning Terminal, download [the latest release of LiT](https://github.com/lightninglabs/lightning-terminal/releases) and follow [the installation instructions of LiT](https://github.com/lightninglabs/lightning-terminal#execution)
## Building the binaries from source
### Building the binaries from source
To build both the `poold` and `pool` binaries from the source code, at least the
`go 1.14` and `make` must be installed.
To build both the `poold` and `pool` binaries from the source code, at least the `go 1.14` and `make` must be installed.
To download the code, compile and install it, the following commands can then
be run:
To download the code, compile and install it, the following commands can then be run:
```shell script
$ git clone https://github.com/lightninglabs/pool
$ cd pool
$ make install
```
\`\`\`shell script $ git clone [https://github.com/lightninglabs/pool](https://github.com/lightninglabs/pool) $ cd pool $ make install
```text
This will install the binaries into your `$GOPATH/bin` directory.
## Installing `lnd`
@ -39,25 +51,24 @@ enabled**:
$ make install tags="signrpc walletrpc chainrpc invoicesrpc"
```
### Running `poold`
## Running `poold`
If `lnd` is configured with the default values and is running on the same machine, `poold` will be able to connect to it automatically and can be started by simply running:
If `lnd` is configured with the default values and is running on the same
machine, `poold` will be able to connect to it automatically and can be started
by simply running:
\`\`\`shell script $ poold
## Or if you want to do everything in the same terminal and run poold in the
## background:
```shell script
$ poold
# Or if you want to do everything in the same terminal and run poold in the
# background:
$ poold &
## For testnet mode, you'll need to specify the network as mainnet is the
## default:
# For testnet mode, you'll need to specify the network as mainnet is the
# default:
$ poold --network=testnet
```
```text
In the case that `lnd` is running on a remote node, the `tls.cert` and all
`*.macaroon` files from the `lnd` data directory need to be copied to the
machine where `poold` is running.
@ -71,35 +82,44 @@ $ poold --lnd.host=<the_remote_host_IP_address>:10009 \
--lnd.tlspath=/some/directory/with/lnd/data/tls.cert
```
To persist this configuration, these values can also be written to a configuration file, located in `~/.pool/<network>/pool.conf`, for example:
To persist this configuration, these values can also be written to a
configuration file, located in `~/.pool/<network>/pool.conf`, for example:
> ~/.pool/mainnet/pool.conf
>
> ```text
> lnd.host=<the_remote_host_IP_address>:10009
> lnd.macaroondir=/some/directory/with/lnd/data/macaroons
> lnd.tlspath=/some/directory/with/lnd/data/tls.cert
> ```
```text
lnd.host=<the_remote_host_IP_address>:10009
lnd.macaroondir=/some/directory/with/lnd/data/macaroons
lnd.tlspath=/some/directory/with/lnd/data/tls.cert
```
### Configuration options
## Configuration options
There is a range of operational settings that can be set to change the default logging behavior or change the directories where `poold` stores its data. To see the full list of options, run `poold --help`.
There is a range of operational settings that can be set to change the default
logging behavior or change the directories where `poold` stores its data. To
see the full list of options, run `poold --help`.
The following list only includes flags that have an impact on the match making or business related behavior of the Pool trader daemon:
The following list only includes flags that have an impact on the match making
or business related behavior of the Pool trader daemon:
| Flag | Required | Default Value | Description |
| :--- | :--- | :--- | :--- |
| Flag | Required | Default Value | Description |
|-------------|----------|---------------|-------------------------------------|
| `newnodesonly` | No | `false` | If set to `true` the daemon will only buy channels from nodes it does not yet have channels with |
## Authentication and transport security
# Authentication and transport security
The gRPC and REST connections of `poold` are encrypted with TLS and secured with macaroon authentication the same way `lnd` is.
The gRPC and REST connections of `poold` are encrypted with TLS and secured with
macaroon authentication the same way `lnd` is.
If no custom base directory is set then the TLS certificate is stored in `~/.pool/<network>/tls.cert` and the base macaroon in `~/.pool/<network>/pool.macaroon`.
If no custom base directory is set then the TLS certificate is stored in
`~/.pool/<network>/tls.cert` and the base macaroon in
`~/.pool/<network>/pool.macaroon`.
The `pool` command will pick up these file automatically on mainnet if no custom base directory is used. For other networks it should be sufficient to add the `--network` flag to tell the CLI in what sub directory to look for the files.
The `pool` command will pick up these file automatically on mainnet if no custom
base directory is used. For other networks it should be sufficient to add the
`--network` flag to tell the CLI in what sub directory to look for the files.
For more information on macaroons, [see the macaroon documentation of lnd.](https://github.com/lightningnetwork/lnd/blob/master/docs/macaroons.md)
**NOTE**: pool's macaroons are independent from `lnd`'s. The same macaroon cannot be used for both `poold` and `lnd`.
For more information on macaroons,
[see the macaroon documentation of lnd.](https://github.com/lightningnetwork/lnd/blob/master/docs/macaroons.md)
**NOTE**: pool's macaroons are independent from `lnd`'s. The same macaroon
cannot be used for both `poold` and `lnd`.

2
docs/lightning_pool.md Normal file
View file

@ -0,0 +1,2 @@
# Lightning Pool: A Non-Custodial Channel Lease Marketplace

View file

@ -4,19 +4,44 @@
Now that we have our account set up and funded, it's time to trade some channels!
There are two types of orders in the current version of Pool: asks, and bids. You submit an ask when you have some coins that you want to _lease out_ as inbound liquidity for a certain period of time \(expressed in blocks\), at a fixed rate compounded per block. You submit a bid when you need to acquire inbound liquidity \(ability to receive\), for a given amount of time \(again expressed in blocks\), paying out a fixed rate that compounds per-block.
There are two types of orders in the current version of Pool: asks, and bids. You
submit an ask when you have some coins that you want to _lease out_ as inbound
liquidity for a certain period of time \(expressed in blocks\), at a fixed rate
compounded per block. You submit a bid when you need to acquire inbound liquidity
\(ability to receive\), for a given amount of time \(again expressed in blocks\),
paying out a fixed rate that compounds per-block.
In the alpha version of Lightning Pool, a single lump sum premium is paid after order execution. In future versions, we plan on introducing "coupon channels" which allow for _streaming interest_ to be paid out.
In the alpha version of Lightning Pool, a single lump sum premium is paid after
order execution. In future versions, we plan on introducing "coupon channels"
which allow for _streaming interest_ to be paid out.
One important aspect of the market is that rather than buy/sell satoshis, we use _units_. A unit is simply 100,000 satoshis and represents the _smallest_ channel that can be bought or sold on the auction platform.
One important aspect of the market is that rather than buy/sell satoshis, we use
_units_. A unit is simply 100,000 satoshis and represents the _smallest_ channel
that can be bought or sold on the auction platform.
With that said, let's place some orders to try to earn some yield from this 0.5 BTC that's been burning a hole in our SD card for the past year. We'll place a single order for 10 million satoshis, wanting to receive 0.3% \(30 bps\) over a 2016 block period \(approximately 2 weeks\):
With that said, let's place some orders to try to earn some yield from this 0.5
BTC that's been burning a hole in our SD card for the past year. We'll place a
single order for 10 million satoshis, wanting to receive 0.3% \(30 bps\) over a
2016 block period \(approximately 2 weeks\):
\`\`\`shell script $ pool orders submit ask 10000000 0288096be9917f8ebdfc6eb2701635fe658f4eae1e0274dcce41418b3fb5145732 --interest\_rate\_percent=0.3 --lease\_duration\_blocks=2016
```shell script
$ pool orders submit ask 10000000 0288096be9917f8ebdfc6eb2701635fe658f4eae1e0274dcce41418b3fb5145732 --interest_rate_percent=0.3 --lease_duration_blocks=2016
-- Order Details -- Ask Amount: 0.1 BTC Ask Duration: 2016 Total Premium \(yield from taker\): 0.00029998 BTC Rate Fixed: 1488 Rate Per Block: 0.000001488 \(0.0001488%\) Execution Fee: 0.00010001 BTC Max batch fee rate: 100 sat/vByte Max chain fee: 0.0016325 BTC Confirm order \(yes/no\): yes { "accepted\_order\_nonce": "e3dbd57e8c22e895cbe705a4ec5ce65bdd766de4fc6d90c8bed404da8e7cbebc" }
-- Order Details --
Ask Amount: 0.1 BTC
Ask Duration: 2016
Total Premium (yield from taker): 0.00029998 BTC
Rate Fixed: 1488
Rate Per Block: 0.000001488 (0.0001488%)
Execution Fee: 0.00010001 BTC
Max batch fee rate: 100 sat/vByte
Max chain fee: 0.0016325 BTC
Confirm order (yes/no): yes
{
"accepted_order_nonce": "e3dbd57e8c22e895cbe705a4ec5ce65bdd766de4fc6d90c8bed404da8e7cbebc"
}
```
```text
By leaving off the `--force` flag, we request the final break down to confirm
the details of our order before we put it through.
@ -27,23 +52,60 @@ premium = (rate_fixed / billion) * amount * blocks
29,998 = (1,488/1,000,000,000)*10,000,000*2,016
```
It's important to note that although internally we use a fixed rate per block to compute the final premium, on the command line, we accept the final acceptable premium as a _percentage_. Therefore, when submitting orders, one should place the value that they wish to receive or accept at the end of the lease period. Internally, we'll then compute the _per block lease rate_ and submit the order using _that_.
It's important to note that although internally we use a fixed rate per block to
compute the final premium, on the command line, we accept the final acceptable
premium as a _percentage_. Therefore, when submitting orders, one should place
the value that they wish to receive or accept at the end of the lease period.
Internally, we'll then compute the _per block lease rate_ and submit the order
using _that_.
The duration and fixed rate \(the percentage\) are two important values to pay attention to when placing orders. Given the same amount, and fixed rate, you earn more by leasing out the funds for a _longer_ period of time. Conversely, a taker will pay more if they need the funds for a longer period of time.
The duration and fixed rate \(the percentage\) are two important values to pay
attention to when placing orders. Given the same amount, and fixed rate, you
earn more by leasing out the funds for a _longer_ period of time. Conversely, a
taker will pay more if they need the funds for a longer period of time.
Also notice the _**max batch fee rate**_ break down, that regulates the _highest_ chain fee you're willing to pay to get into a batch. When traders are included in a batch, they split the channel open fee with the party they're matched with, then pay for their account to be spent and re-created. The auctioneer then uses this value during match making to ensure that traders don't pay more _chain fees_ than they intend to. If your desired chain fee is _below_ the current proposed batch chain fee, then your order won't be eligible for execution until chain fees come down somewhat.
Also notice the **_max batch fee rate_** break down, that regulates the _highest_
chain fee you're willing to pay to get into a batch. When traders are included
in a batch, they split the channel open fee with the party they're matched with,
then pay for their account to be spent and re-created. The auctioneer then uses
this value during match making to ensure that traders don't pay more _chain fees_
than they intend to. If your desired chain fee is _below_ the current proposed
batch chain fee, then your order won't be eligible for execution until chain
fees come down somewhat.
Users can use the `--max_batch_fee_rate` value to regulate chain fees.
Take note of the `order_nonce`, it's used through the auction to identify orders, and also for authentication purposes.
Take note of the `order_nonce`, it's used through the auction to identify orders,
and also for authentication purposes.
We can then check out the order we just placed with the following command:
\`\`\`shell script $ pool orders list
```shell script
$ pool orders list
{ ... "details": { "trader\_key": "024010a572c9f89b78b9d024f2be6cd4d42f4b9a80bfee4a5855e85da128c78473", "rate\_fixed": 1488, "amt": "10000000", "max\_batch\_fee\_rate\_sat\_per\_kw": "25000", "order\_nonce": "e3dbd57e8c22e895cbe705a4ec5ce65bdd766de4fc6d90c8bed404da8e7cbebc", "state": "ORDER\_SUBMITTED", "units": 100, "units\_unfulfilled": 100, "reserved\_value\_sat": "10143270", "creation\_timestamp\_ns": "1602679458771936428", "events": \[ \], "min\_units\_match": 10 }, "lease\_duration\_blocks": 2016, "version": 1 ... }
{
...
"details": {
"trader_key": "024010a572c9f89b78b9d024f2be6cd4d42f4b9a80bfee4a5855e85da128c78473",
"rate_fixed": 1488,
"amt": "10000000",
"max_batch_fee_rate_sat_per_kw": "25000",
"order_nonce": "e3dbd57e8c22e895cbe705a4ec5ce65bdd766de4fc6d90c8bed404da8e7cbebc",
"state": "ORDER_SUBMITTED",
"units": 100,
"units_unfulfilled": 100,
"reserved_value_sat": "10143270",
"creation_timestamp_ns": "1602679458771936428",
"events": [
],
"min_units_match": 10
},
"lease_duration_blocks": 2016,
"version": 1
...
}
```
```text
The order hasn't been cleared yet \(state `ORDER_SUBMITTED`\), and it shows up
as 100 units, or 10 million satoshis.
@ -67,7 +129,6 @@ $ pool orders submit ask
```
Help output:
```text
$ pool orders submit ask --help
@ -78,7 +139,7 @@ USAGE:
pool orders submit ask [command options] amt acct_key [--rate_fixed=R] [--max_batch_fee_rate=F] [--lease_duration_blocks=M]
DESCRIPTION:
Create an offer to provide inbound liquidity to an auction participant
by opening a channel to them for a certain time.
@ -92,25 +153,29 @@ OPTIONS:
--max_batch_fee_rate value the maximum fee rate (sat/vByte) to use to for the batch transaction (default: 100)
```
NOTE: The default values shown in the command line help are different from the actual default values that are used. A value of `0` on the command line indicates: _No actual value set, use the internal default value_. See the table below for more information.
NOTE: The default values shown in the command line help are different from the
actual default values that are used. A value of `0` on the command line
indicates: *No actual value set, use the internal default value*. See the table
below for more information.
| Flag | Required | Default Value | Description |
| :--- | :--- | :--- | :--- |
| `interest_rate_percent` | Yes | n/a | The interest rate that should be earned over **the total lease duration**. |
| `amt` | Yes | n/a | The amount of liquidity to offer in satoshis. Must be a multiple of the base unit \(100k sat\). |
| `acct_key` | Yes | n/a | The account's trader key to use to pay for the offered liquidity, the order submission fee and chain fees. |
| `lease_duration_blocks` | No | `2016` | The minimum number of blocks the offered channels need to stay open for in order to satisfy the contract. Distinct markets are available for the different durations. See [lease duration section](orders.md#lease-duration) for more information. |
| `min_chan_amt` | No | 10% of `amt` | The minimum size/capacity of any offered channel. Higher values reduce the match potential but decrease the potential total in chain fees that must be paid. Must be a multiple of the base unit \(100k sat\). See [chain fees section](orders.md#chain-fees) for more information. |
| `max_batch_fee_rate` | No | `100` sat/vByte | The maximum on-chain fee rate at which this order should be eligible to be included in a batch. If the auctioneer estimates a higher fee rate, orders below will be skipped. See [chain fees section](orders.md#chain-fees) for more information. |
| `force` | No | `false` | When set to `true`, no order details will be shown and no confirmation is required. |
| Flag | Required | Default Value | Description |
|-------------------------|----------|---------------|-------------------------------------|
| `interest_rate_percent` | Yes | n/a | The interest rate that should be earned over **the total lease duration**. |
| `amt` | Yes | n/a | The amount of liquidity to offer in satoshis. Must be a multiple of the base unit (100k sat). |
| `acct_key` | Yes | n/a | The account's trader key to use to pay for the offered liquidity, the order submission fee and chain fees. |
| `lease_duration_blocks` | No | `2016` | The minimum number of blocks the offered channels need to stay open for in order to satisfy the contract. Distinct markets are available for the different durations. See [lease duration section](#lease-duration) for more information. |
| `min_chan_amt` | No | 10% of `amt` | The minimum size/capacity of any offered channel. Higher values reduce the match potential but decrease the potential total in chain fees that must be paid. Must be a multiple of the base unit (100k sat). See [chain fees section](#chain-fees) for more information. |
| `max_batch_fee_rate` | No | `100` sat/vByte | The maximum on-chain fee rate at which this order should be eligible to be included in a batch. If the auctioneer estimates a higher fee rate, orders below will be skipped. See [chain fees section](#chain-fees) for more information. |
| `force` | No | `false` | When set to `true`, no order details will be shown and no confirmation is required. |
### Bid orders
Command for submitting a bid order:
\`\`\`shell script $ pool orders submit bid
```shell script
$ pool orders submit bid
```
```text
Help output:
```text
NAME:
@ -120,7 +185,7 @@ USAGE:
pool orders submit bid [command options] amt acct_key [--rate_fixed=R] [--max_batch_fee_rate=F] [--lease_duration_blocks=M]
DESCRIPTION:
Place an offer for acquiring inbound liquidity by lending
funding capacity from another participant in the order book.
@ -135,32 +200,53 @@ OPTIONS:
--max_batch_fee_rate value the maximum fee rate (sat/vByte) to use to for the batch transaction (default: 100)
```
NOTE: The default values shown in the command line help are different from the actual default values that are used. A value of `0` on the command line indicates: _No actual value set, use the internal default value_. See the table below for more information.
NOTE: The default values shown in the command line help are different from the
actual default values that are used. A value of `0` on the command line
indicates: *No actual value set, use the internal default value*. See the table
below for more information.
| Flag | Required | Default Value | Description |
| :--- | :--- | :--- | :--- |
| `interest_rate_percent` | Yes | n/a | The maximum interest rate that should be paid for leasing a channel, calculated over **the total lease duration**. |
| `amt` | Yes | n/a | The amount of liquidity to lease in satoshis. Must be a multiple of the base unit \(100k sat\). |
| `acct_key` | Yes | n/a | The account's trader key to use to pay for the lease premium, order submission fee and chain fees. |
| `lease_duration_blocks` | No | `2016` | The minimum number of blocks the leased channels must stay open for in order to satisfy the contract. Distinct markets are available for the different durations. See [lease duration section](orders.md#lease-duration) for more information. |
| `min_chan_amt` | No | 10% of `amt` | The minimum size/capacity of any leased channel. Higher values reduce the match potential but decrease the potential total in chain fees that must be paid. Must be a multiple of the base unit \(100k sat\). See [chain fees section](orders.md#chain-fees) for more information. |
| `min_node_tier` | No | `1` | The minimum quality of node this bid should be matched with. The default \(if no command line flag is set\) is "Tier 1" which means the bid is only matched with asks from nodes that are considered "good". When manually setting this to `--min_node_tier=0` then asks from all nodes should be considered, regardless of their "quality". |
| `max_batch_fee_rate` | No | `100` sat/vByte | The maximum on-chain fee rate at which this order should be eligible to be included in a batch. If the auctioneer estimates a higher fee rate, orders below will be skipped. See [chain fees section](orders.md#chain-fees) for more information. |
| `force` | No | `false` | When set to `true`, no order details will be shown and no confirmation is required. |
| Flag | Required | Default Value | Description |
|-------------------------|----------|---------------|-------------------------------------|
| `interest_rate_percent` | Yes | n/a | The maximum interest rate that should be paid for leasing a channel, calculated over **the total lease duration**. |
| `amt` | Yes | n/a | The amount of liquidity to lease in satoshis. Must be a multiple of the base unit (100k sat). |
| `acct_key` | Yes | n/a | The account's trader key to use to pay for the lease premium, order submission fee and chain fees. |
| `lease_duration_blocks` | No | `2016` | The minimum number of blocks the leased channels must stay open for in order to satisfy the contract. Distinct markets are available for the different durations. See [lease duration section](#lease-duration) for more information. |
| `min_chan_amt` | No | 10% of `amt` | The minimum size/capacity of any leased channel. Higher values reduce the match potential but decrease the potential total in chain fees that must be paid. Must be a multiple of the base unit (100k sat). See [chain fees section](#chain-fees) for more information. |
| `min_node_tier` | No | `1` | The minimum quality of node this bid should be matched with. The default (if no command line flag is set) is "Tier 1" which means the bid is only matched with asks from nodes that are considered "good". When manually setting this to `--min_node_tier=0` then asks from all nodes should be considered, regardless of their "quality". |
| `max_batch_fee_rate` | No | `100` sat/vByte | The maximum on-chain fee rate at which this order should be eligible to be included in a batch. If the auctioneer estimates a higher fee rate, orders below will be skipped. See [chain fees section](#chain-fees) for more information. |
| `force` | No | `false` | When set to `true`, no order details will be shown and no confirmation is required. |
## Lease duration
The lease duration dictates the duration of the contract that the maker \(submitter of the ask order\) and the taker \(submitter of the bid order\) enter when being matched by the auctioneer. That means that the maker must provide the offered liquidity **at least** for the selected number of blocks. The maker is not allowed to close the channel before the agreed upon lease duration has elapsed. The maker **may** close the channel after the duration is over but is not obligated to do so. If a channel is economically viable, further routing fees might be collected when keeping the channel open.
The lease duration dictates the duration of the contract that the maker
(submitter of the ask order) and the taker (submitter of the bid order) enter
when being matched by the auctioneer. That means that the maker must provide the
offered liquidity **at least** for the selected number of blocks. The maker is
not allowed to close the channel before the agreed upon lease duration has
elapsed. The maker **may** close the channel after the duration is over but is
not obligated to do so. If a channel is economically viable, further routing
fees might be collected when keeping the channel open.
In contrast, the taker of the channel is always allowed to close the channel. They pay the premium for the whole duration upfront, and it is therefore to their own disadvantage to close the channel prematurely.
In contrast, the taker of the channel is always allowed to close the channel.
They pay the premium for the whole duration upfront, and it is therefore to
their own disadvantage to close the channel prematurely.
To allow the formation of distinct premium rates over different durations, the possible lease durations are fixed and defined by the auctioneer. The current list of possible lease durations can be queried by running the following command:
To allow the formation of distinct premium rates over different durations, the
possible lease durations are fixed and defined by the auctioneer. The current
list of possible lease durations can be queried by running the following
command:
\`\`\`shell script $ pool auction leasedurations
```shell script
$ pool auction leasedurations
{ "lease\_durations": { "2016": true, "4032": false, } }
{
"lease_durations": {
"2016": true,
"4032": false,
}
}
```
```text
The integer value is the lease duration in blocks. The boolean value indicates
whether matchmaking in the given duration market is currently enabled or not.
When adding a new lease duration the auctioneer might not enable matchmaking
@ -191,7 +277,8 @@ $ pool auction fee
}
```
Based on these **example** values, a matched order of 7 units \(700k satoshis\) would be charged an execution fee of 986 satoshis:
Based on these **example** values, a matched order of 7 units (700k satoshis)
would be charged an execution fee of 986 satoshis:
```text
execution_fee = base_fee + (fee_rate / million) * match_amount
@ -200,24 +287,41 @@ execution_fee = base_fee + (fee_rate / million) * match_amount
## Chain fees
Each successfully executed order will result in at least one channel output being created in the batch transaction that is published to the Bitcoin network. Additionally, because an account must be spent for an order to be executed, an input per involved account is also added to the transaction, and, if there is a remaining balance, the change goes back to a newly created output for that account.
Each successfully executed order will result in at least one channel output
being created in the batch transaction that is published to the Bitcoin network.
Additionally, because an account must be spent for an order to be executed, an
input per involved account is also added to the transaction, and, if there is a
remaining balance, the change goes back to a newly created output for that
account.
In an example worst-case-scenario, a bid order for buying one channel can result in one input and two outputs being created on-chain. Each trader is charged fully for the transaction weight they produce with their account inputs and outputs. The cost for the new channel output is split in half between the maker and the taker.
In an example worst-case-scenario, a bid order for buying one channel can result
in one input and two outputs being created on-chain. Each trader is charged
fully for the transaction weight they produce with their account inputs and
outputs. The cost for the new channel output is split in half between the maker
and the taker.
Assuming we have a bid order over 5 units \(500k satoshis\) and an account that is 10 times that size, we'd occupy 162 virtual bytes of chain space:
Assuming we have a bid order over 5 units (500k satoshis) and an account that is
10 times that size, we'd occupy 162 virtual bytes of chain space:
```text
size_vBytes = acct_input_size + 0.5 * chan_output_size + acct_output_size
162 ~= ~98 + 0.5 * 43 + 43
```
Assuming the auctioneer estimates a current network fee rate of 34 sat/vByte, that order would cost `162 * 34 = 5,508` satoshi in chain fees to execute.
Assuming the auctioneer estimates a current network fee rate of 34 sat/vByte,
that order would cost `162 * 34 = 5,508` satoshi in chain fees to execute.
The auctioneer always tries to be economical with its fee estimation, but fee estimation is hard, and the fee market remains unpredictable. To give traders some protection against excessive fees, the `--max_batch_fee_rate` can be set for any order submitted that communicates to the auctioneer that the order shouldn't be considered for matching if the current estimation is higher than that rate.
The auctioneer always tries to be economical with its fee estimation, but fee
estimation is hard, and the fee market remains unpredictable. To give traders
some protection against excessive fees, the `--max_batch_fee_rate` can be set
for any order submitted that communicates to the auctioneer that the order
shouldn't be considered for matching if the current estimation is higher than
that rate.
### Max chain fee estimation
When submitting an order, the command line shows a summary of the expected fees, as shown in our initial example:
When submitting an order, the command line shows a summary of the expected fees,
as shown in our initial example:
```text
Execution Fee: 0.00010001 BTC
@ -225,57 +329,53 @@ Max batch fee rate: 100 sat/vByte
Max chain fee: 0.0016325 BTC
```
The value shown as `Max chain fee` can look pretty scary. But it is important to note that the value is considered to be the **absolute worst-case fee**.
The value shown as `Max chain fee` can look pretty scary. But it is important
to note that the value is considered to be the **absolute worst-case fee**.
The maximum chain fee is calculated based on how many potential partial matches an order could go through \(assuming it would always only match the minimum match size or minimum channel size\). And for each of those partial matches the chain fee calculation as shown in the previous section would be performed with the given `Max batch fee rate`. It is quite unlikely however that the maximum fee is ever required to be paid for an order to be executed.
The maximum chain fee is calculated based on how many potential partial matches
an order could go through (assuming it would always only match the minimum match
size or minimum channel size). And for each of those partial matches the chain
fee calculation as shown in the previous section would be performed with the
given `Max batch fee rate`. It is quite unlikely however that the maximum fee is
ever required to be paid for an order to be executed.
To reduce the value of this worst-case estimation, there are two possible flags that can be used to influence it:
* `--min_chan_amt`: The minimum match size or minimum channel size. Instructs
the auctioneer to only match the order with a counterpart that can at least
fill the given amount in one match. By default, this values is set to 10% of
the full order amount. Increasing the value makes it less likely to find a
match candidate but reduces the number of times chain fees have to be paid.
Increasing the value to 100% of the order amount is equivalent to a
"kill-or-fill" order that is either executed in one part or not at all.
* `--max_batch_fee_rate`: The maximum network fee rate the order should be
considered for. Orders with a value higher than what the auctioneer estimates
at the time of matchmaking will be excluded for that batch. Setting this
value too low might result in orders not being executed at all or only when
the mempools are almost empty.
To reduce the value of this worst-case estimation, there are two possible flags
that can be used to influence it:
* `--min_chan_amt`: The minimum match size or minimum channel size. Instructs
the auctioneer to only match the order with a counterpart that can at least
fill the given amount in one match. By default, this values is set to 10% of
the full order amount. Increasing the value makes it less likely to find a
match candidate but reduces the number of times chain fees have to be paid.
Increasing the value to 100% of the order amount is equivalent to a
"kill-or-fill" order that is either executed in one part or not at all.
* `--max_batch_fee_rate`: The maximum network fee rate the order should be
considered for. Orders with a value higher than what the auctioneer estimates
at the time of matchmaking will be excluded for that batch. Setting this
value too low might result in orders not being executed at all or only when
the mempools are almost empty.
## Extensibility
At the moment there are only two restrictions that users can set on _who_ their orders will be matched against. There is the global `--newnodesonly` flag which will cause the trader daemon to reject any matches with nodes that its connected `lnd` node already has channels with.
At the moment there are only two restrictions that users can set on _who_ their
orders will be matched against. There is the global `--newnodesonly` flag which
will cause the trader daemon to reject any matches with nodes that its connected
`lnd` node already has channels with.
Takers can additionally influence the "quality" of the nodes they want their bid orders to be matched against by setting the `--min_node_tier` when creating the order.
Takers can additionally influence the "quality" of the nodes they want their bid
orders to be matched against by setting the `--min_node_tier` when creating the
order.
In the future, more matching restrictions will likely be implemented, for example:
* Specifying a concrete list of `lnd` node public keys that an order should
be matched with.
* Instant order: Either be matched successfully in the next batch or be
canceled.
* Buying channels for someone else \(a.k.a. "Sidecar Channels"\): When creating
a bid order, a third party's `lnd` node pubkey can be specified that will
receive the leased channel instead of the node of the bidder.
To allow these future upgrades to work seamlessly, a version field was added to the order submission protocol from the beginning. With this version field, the trader and auctioneer always know what fields an order is supposed to have set and therefore what fields are covered by the trader's order signature.
In the future, more matching restrictions will likely be implemented, for
example:
* Specifying a concrete list of `lnd` node public keys that an order should
be matched with.
* Instant order: Either be matched successfully in the next batch or be
canceled.
* Buying channels for someone else (a.k.a. "Sidecar Channels"): When creating
a bid order, a third party's `lnd` node pubkey can be specified that will
receive the leased channel instead of the node of the bidder.
To allow these future upgrades to work seamlessly, a version field was added to
the order submission protocol from the beginning. With this version field, the
trader and auctioneer always know what fields an order is supposed to have set
and therefore what fields are covered by the trader's order signature.