mirror of
https://github.com/lightning/blips.git
synced 2024-11-19 00:50:02 +01:00
bLIP-0012: Hosted Channels (#17)
This commit is contained in:
parent
3286ece33d
commit
42777f02e1
@ -24,3 +24,4 @@ For more detail on the process, please read [bLIP-0001](./blip-0001.md) and
|
||||
| [3](./blip-0003.md) | Keysend | Valentine Wallace | Active |
|
||||
| [10](./blip-0010.md) | Podcasting 2.0 | Satoshis Stream | Active |
|
||||
| [11](./blip-0011.md) | NameDesc | Hampus Sjöberg | Active |
|
||||
| [17](./blip-0017.md) | Hosted Channels | Anton Kumaigorodskiy | Active |
|
||||
|
24
blip-0002.md
24
blip-0002.md
@ -43,9 +43,10 @@ Feature bits in the `0`-`255` range are reserved for BOLTs: bLIPs must use featu
|
||||
|
||||
bLIPs may reserve feature bits by adding them to the following table:
|
||||
|
||||
| Bits | Name | Description | Context | Dependencies | Link |
|
||||
|---------|----------------------|-------------------------------------------------|----------------|--------------------------------|--------------------------------|
|
||||
| 54/55 | `keysend` | A form of spontaneous payment | N | `var_onion_optin` | [bLIP 3](./blip-0003.md) |
|
||||
| Bits | Name | Description | Context | Dependencies | Link |
|
||||
| --------- | ---------------------- | ------------------------------------------------- | ---------------- | -------------------------------- | -------------------------------- |
|
||||
| 54/55 | `keysend` | A form of spontaneous payment | N | `var_onion_optin` | [bLIP 3](./blip-0003.md) |
|
||||
| 256/257 | `hosted_channels` | This node accepts requests for hosted channels | IN | | [bLIP 17](./blip-0017.md) |
|
||||
|
||||
### Messages
|
||||
|
||||
@ -55,9 +56,20 @@ that every lightning implementation understands.
|
||||
Message types in the `0`-`32767` range are reserved for BOLTs: bLIPs must use message types in the `32768`-`65535` range.
|
||||
bLIPs may create new messages and reserve their type in the following table:
|
||||
|
||||
| Type | Name | Link |
|
||||
|-------|-----------------------------|--------------------------------|
|
||||
| 32768 | `message_name` | Link to the corresponding bLIP |
|
||||
| Type | Name | Link |
|
||||
| ------- | ------------------------------- | -------------------------- |
|
||||
| 65535 | `invoke_hosted_channel` | [bLIP 17](./blip-0017.md) |
|
||||
| 65533 | `init_hosted_channel` | [bLIP 17](./blip-0017.md) |
|
||||
| 65531 | `last_cross_signed_state` | [bLIP 17](./blip-0017.md) |
|
||||
| 65529 | `state_update` | [bLIP 17](./blip-0017.md) |
|
||||
| 65527 | `state_override` | [bLIP 17](./blip-0017.md) |
|
||||
| 65525 | `hosted_channel_branding` | [bLIP 17](./blip-0017.md) |
|
||||
| 65511 | `ask_channel_branding` | [bLIP 17](./blip-0017.md) |
|
||||
| 63505 | `hc_update_add_htlc` | [bLIP 17](./blip-0017.md) |
|
||||
| 63503 | `hc_update_fulfill_htlc` | [bLIP 17](./blip-0017.md) |
|
||||
| 63501 | `hc_updated_fail_htlc` | [bLIP 17](./blip-0017.md) |
|
||||
| 63499 | `hc_update_fail_malformed_htlc` | [bLIP 17](./blip-0017.md) |
|
||||
| 63497 | `hc_error` | [bLIP 17](./blip-0017.md) |
|
||||
|
||||
### TLV fields in BOLT messages
|
||||
|
||||
|
366
blip-0017.md
Normal file
366
blip-0017.md
Normal file
@ -0,0 +1,366 @@
|
||||
```
|
||||
bLIP: 0017
|
||||
Title: Hosted Channels
|
||||
Status: Active
|
||||
Author: Anton Kumaigorodski <akumaigorodski@gmail.com>
|
||||
fiatjaf <fiatjaf@gmail.com>
|
||||
Created: 2022-07-07
|
||||
License: CC0
|
||||
```
|
||||
|
||||
## Abstract
|
||||
|
||||
Hosted Channels is a specification for auditable Lightning-like channels backed
|
||||
only by trust from a client in a host.
|
||||
|
||||
This bLIP serves to document what is already supported by some wallets and daemons
|
||||
(see [Reference Implementations](#reference-implementations)) and to encourage new
|
||||
implementations.
|
||||
|
||||
## Copyright
|
||||
|
||||
This bLIP is licensed under the CC0 license.
|
||||
|
||||
## Motivation
|
||||
|
||||
Hosted Channels are an improvement over the traditional custodial Lightning wallet
|
||||
model. They describe the roles of "host" and "client", the client being the peer
|
||||
that is trusting the host to allow them to spend from the channel according to their
|
||||
balance.
|
||||
|
||||
Like custodial wallets, hosted channel clients do not have to have any previous
|
||||
Bitcoin UTXO or touch the chain in any way; they gain the ability to receive
|
||||
payments immediately; and they do not have to keep track of a channel state history
|
||||
and all the pitfalls involved on that, or keep track of Bitcoin transactions or fees.
|
||||
|
||||
Unlike custodial wallets, hosted channel clients are not "accounts" in a central
|
||||
server, they communicate through signed messages over the Lightning protocol and are
|
||||
otherwise anonymous to the hosts; they perform client-side routing and their hosts only
|
||||
ever see onions to forward, never the final destination of a payment; they can open
|
||||
multiple channels to different hosts and send MPP payments over these channels, further
|
||||
improving their anonymity; and their channel state is signed by both parties, so
|
||||
they are immune to hosts that may tamper with balances from their actual state on
|
||||
purpose or by mistake. All this also means clients must be online to send and receive,
|
||||
as they must sign state updates.
|
||||
|
||||
## Specification
|
||||
|
||||
The protocol consists of messages being passed through [bolt01][bolt01] connections and
|
||||
mimics [bolt02][bolt02], with different messages that serve analogous purposes.
|
||||
|
||||
Importantly, it defines two distinct roles in the channel: that of the HOST and that of
|
||||
the CLIENT. The CLIENT being the party who trusts the HOST with its funds when it requests
|
||||
a hosted channel and receives payments into it.
|
||||
|
||||
### Channel Establishment
|
||||
|
||||
This is a diagram that illustrates the entire channel establishment process.
|
||||
|
||||
C is the CLIENT, H is the HOST.
|
||||
|
||||
+-------+ +-------+
|
||||
| |--(1)--- invoke_hosted_channel -->| |
|
||||
| |<-(2)--- init_hosted_channel -----| |
|
||||
| C | | H |
|
||||
| |--(3)------ state_update -------->| |
|
||||
| |<-(4)------ state_update ---------| |
|
||||
+-------+ +-------+
|
||||
|
||||
The following sections about the messages will detail this process further.
|
||||
|
||||
|
||||
### The `invoke_hosted_channel` Message
|
||||
|
||||
This message is sent by the CLIENT when it wants to request a new hosted channel from a
|
||||
HOST, but also every time it establishes a connection to the HOST, to activate that
|
||||
channel and check if the two parties are in agreement with regards to the channel state.
|
||||
|
||||
1. type: 65535 (`invoke_hosted_channel`)
|
||||
2. data:
|
||||
* [`chain_hash`:`chain_hash`]
|
||||
* [`u16`:`len`]
|
||||
* [`len*byte`:`refund_scriptpubkey`]
|
||||
* [`u16`:`len`]
|
||||
* [`len*byte`:`secret`]
|
||||
|
||||
The `refund_scriptpubkey` is similar to `scriptpubkey` in [bolt02][bolt02-scriptpubkey]
|
||||
and must be provided in case HOST wants to terminate the channel but cannot contact the
|
||||
CLIENT.
|
||||
|
||||
The `secret` is an optional blob that can be used by HOST to tweak channel parameters
|
||||
in multiple ways: offer an initial balance, tweak the capacity, only allow cliets with
|
||||
a given secret etc.
|
||||
|
||||
Upon receiving an `invoke_hosted_channel` message, the HOST, if willing to establish the
|
||||
channel, must reply with an `init_hosted_channel` message. If the CLIENT already has a
|
||||
channel established, the HOST must instead reply with a `last_cross_signed_state`.
|
||||
|
||||
### The `init_hosted_channel` Message
|
||||
|
||||
This is sent by the HOST after a new CLIENT requests a channel using the
|
||||
`invoke_hosted_channel` message.
|
||||
|
||||
1. type: 65533 (`init_hosted_channel`)
|
||||
2. data:
|
||||
* [`u64`:`max_htlc_value_in_flight_msat`]
|
||||
* [`u64`:`htlc_minimum_msat`]
|
||||
* [`u16`:`max_accepted_htlcs`]
|
||||
* [`u64`:`channel_capacity_msat`]
|
||||
* [`u64`:`initial_client_balance_msat`]
|
||||
* [`u16`:`len`]
|
||||
* [`len*byte`:`features`]
|
||||
|
||||
It contains the parameters of the hosted channel offered from HOST to CLIENT.
|
||||
|
||||
### The `last_cross_signed_state` Message
|
||||
|
||||
This message essentially represents the _state of the channel_ and the only
|
||||
piece of data that must be stored by peers. It is different for each peer or rather
|
||||
each peer sees the reverse of what the other peer sees, but it includes a signature
|
||||
by each peer of the other peer's view, thus the name "cross-signed".
|
||||
|
||||
1. type: 65531 (`last_cross_signed_state`)
|
||||
2. data:
|
||||
* [`bool`: `is_host`]
|
||||
* [`u16`:`len`]
|
||||
* [`len*byte`:`last_refund_scriptpubkey`]
|
||||
* [[`init_hosted_channel`](#the-init_hosted_channel-message):`init_hosted_channel`]
|
||||
* [`u32`:`block_day`]
|
||||
* [`u64`:`local_balance_msat`]
|
||||
* [`u64`:`remote_balance_msat`]
|
||||
* [`u32`:`local_updates`]
|
||||
* [`u32`:`remote_updates`]
|
||||
* [`u16`:`num_incoming_htlcs`]
|
||||
* [`num_incoming_htlcs`*[`update_add_htlc`][update_add_htlc]:`incoming_htlcs`]
|
||||
* [`u16`:`num_outgoing_htlcs`]
|
||||
* [`num_outgoing_htlcs`*[`update_add_htlc`][update_add_htlc]:`outgoing_htlcs`]
|
||||
* [`signature`:`remote_sig_of_local`]
|
||||
* [`signature`:`local_sig_of_remote`]
|
||||
|
||||
The `is_host` property must be set to either `true` or `false` depending on the side
|
||||
that is signing it.
|
||||
|
||||
The `block_day` is the current Bitcoin block height divided by 144 and rounded down.
|
||||
|
||||
The `last_refund_scriptpubkey` is the value of `refund_scriptpubkey` received in the
|
||||
last `invoke_hosted_channel` sent by CLIENT.
|
||||
|
||||
`local_updates` and `remote_updates` are the number of updates each party has added to
|
||||
the channel over the time, these numbers increase every time a peer sends an
|
||||
`update_add_htlc`, `update_fail_htlc`, `update_fail_malformed_htlc` or `update_fulfill_htlc`.
|
||||
|
||||
Upon receiving this message the CLIENT must check the signatures and proceed as follows:
|
||||
|
||||
1. if the number of `local_updates` + `remote_updates` is smaller than what they have
|
||||
stored, the CLIENT must ignore the message and send their own `last_cross_signed_state`.
|
||||
In this case the HOST must accept the state as sent by the peer, **reverse** it and
|
||||
override their own state with the state received from CLIENT.
|
||||
2. if the number of updates is the same that means CLIENT and HOST are on agreement.
|
||||
The CLIENT must still sent their `last_cross_signed_state` so the HOST will acknowledge
|
||||
that and the channel can become "active".
|
||||
3. if the number of updates is greater than what the CLIENT has stored, they must
|
||||
**reverse** it and replace their local state with that, then send their local updated
|
||||
`last_cross_signed_state` to HOST so they can acknowledge that. From the point of view
|
||||
of the HOST there is no difference between cases 2 and 3.
|
||||
|
||||
If the signatures are bad the peer must send an [`error`](#the-error-message) and put
|
||||
the channel in an "errored" state until it can be fixed manually.
|
||||
|
||||
To **reverse** a `last_cross_signed_state` means to see it as the channel peer would, i.e.
|
||||
change `is_host` from `true` to `false` and vice-versa; to set `local_updates` to
|
||||
`remote_updates` and vice-versa; to to set `local_balance_msat` to `remote_balance_msat`
|
||||
and vice-versa, to set `incoming_htlcs` to `outgoing_htlcs` and vice-versa and finally
|
||||
(although this part is not relevant when signing a `state_update`) to set
|
||||
`local_sig_of_remote` to `remote_sig_of_local` and vice-versa.
|
||||
|
||||
### The `state_update` Message
|
||||
|
||||
After receiving an `init_hosted_channel` the CLIENT should check if it likes its params,
|
||||
then send this message.
|
||||
|
||||
Upon receiving it, the HOST will then send its own `state_update` and from the two
|
||||
`state_update`s
|
||||
combined both parties should be able to construct their `last_cross_signed_state`
|
||||
independently, which are the effective channel "state" that both parties must store and
|
||||
keep track of.
|
||||
|
||||
1. type: 65529 (`state_update`)
|
||||
2. data:
|
||||
* [`u32`:`block_day`]
|
||||
* [`u32`:`local_updates`]
|
||||
* [`u32`:`remote_updates`]
|
||||
* [`signature`:`local_sig_of_remote`]
|
||||
|
||||
The initial value for `local_updates` and `remote_updates` is `0`.
|
||||
|
||||
The `local_sig_of_remote` is a signature over the **reverse** of the current value for
|
||||
`last_cross_signed_state` known to the signer, i.e. the peer's view of the channel
|
||||
state. The calculation of the hash to be signed can be seen [in this piece of source code][hosted_sighash].
|
||||
|
||||
### Normal Operation
|
||||
|
||||
The normal channel operation consists in peers offering the default [bolt02][bolt02]
|
||||
"update messages" to each other, `update_add_htlc`, `update_fail_htlc`,
|
||||
`update_fail_malformed_htlc` and `update_fulfill_htlc`, then following them with a
|
||||
`state_update` representing what will be the next state of the channel after the updates
|
||||
are accepted by the peer.
|
||||
|
||||
The peer must respond with their own `state_update` after applying the received update
|
||||
to their local state view.
|
||||
|
||||
There is no distinction between HOST and CLIENT here.
|
||||
|
||||
+-------+ +-------+
|
||||
| |--(1)---- update_add_htlc ---->| |
|
||||
| |--(2)---- update_add_htlc ---->| |
|
||||
| |--(3)---- state_update ------->| |
|
||||
| |<-(4)---- state_update --------| |
|
||||
| | | |
|
||||
| A |<-(5)-- update_fulfill_htlc ---| B |
|
||||
| |<-(6)-- state_update ----------| |
|
||||
| |--(7)-- state_update --------->| |
|
||||
| | | |
|
||||
| |<-(8)--- update_fail_htlc -----| |
|
||||
| |<-(9)--- state_update ---------| |
|
||||
| |-(10)--- state_update -------->| |
|
||||
+-------+ +-------+
|
||||
|
||||
To construct the `state_update` message, for each update sent or received, the peers must
|
||||
increase the `local_updates` or `remote_updates` count of their next (still uncommitted,
|
||||
unsigned) state (`last_cross_signed_state`), change the balances accordingly, then sign the
|
||||
**reverse** of that.
|
||||
|
||||
`state_update` messages with `local_updates` or `remote_updates` counts smaller than the
|
||||
current view of a peer's next state must be ignored, and only when their counts and signature
|
||||
matches a the receiver's current view of the next state that state can be considered
|
||||
committed, i.e. cross-signed.
|
||||
|
||||
### The `update_add_htlc` Message
|
||||
|
||||
This is the same [`update_add_htlc` message][update_add_htlc] from bolt01,
|
||||
but using the type `63505`.
|
||||
|
||||
### The `update_fulfill_htlc` Message
|
||||
|
||||
This is the same [`update_fulfill_htlc` message][update_fulfill_htlc] from bolt01,
|
||||
but using the type `63503`.
|
||||
|
||||
### The `update_fail_htlc` Message
|
||||
|
||||
This is the same [`update_fail_htlc` message][update_fail_htlc] from bolt01,
|
||||
but using the type `63501`.
|
||||
|
||||
### The `update_fail_malformed_htlc` Message
|
||||
|
||||
This is the same [`update_fail_malformed_htlc` message][update_fail_malformed_htlc] from bolt01,
|
||||
but using the type `63499`.
|
||||
|
||||
### The `error` Message
|
||||
|
||||
This is the same [`error` message][error] from bolt02, but using the type `63497`.
|
||||
|
||||
### Dealing with problems
|
||||
|
||||
If a peer receives a preimage from a payment sent upstream, but can't contact their hosted
|
||||
peer to send the `update_fulfill_htlc` and effectively update the state, they can opt to
|
||||
publish the preimage to the Bitcoin chain in an `OP_RETURN` output. The output scriptPubKey
|
||||
must take the form of either `OP_RETURN <32-byte-preimage>` or `OP_RETURN <32-byte-preimage>
|
||||
<32-byte-preimage>` (for publishing two preimages in the same output). Peers should also
|
||||
monitor the blockchain in search for preimages that may have been published for their
|
||||
in-flight HTLCs, as the presence of these preimages onchain effectively proves the payment,
|
||||
even if the peer hasn't sent an `update_fulfill_htlc` update through the normal means.
|
||||
|
||||
If an HTLC that is incoming through a hosted channel times out and there is no sight of its
|
||||
preimage anywhere, it is considered failed, and the peer who is holding that must send an
|
||||
[`error`](#the-error-message) and put the channel in an "errored" state until it can be
|
||||
fixed manually.
|
||||
|
||||
When the state is "errored" it must not accept new updates _except_ `update_fail_htlc` and
|
||||
`update_fulfill_htlc` for non-expired pending HTLCs, as good HTLCs may still be resolved
|
||||
peacefully independent of the conflict caused by others.
|
||||
|
||||
After a channel reaches an "errored" state peers can agree through extra-protocol means to
|
||||
reactivate it under a certain balance distribution. Once that happens the HOST must send
|
||||
an `state_override` message and the CLIENT must accept it.
|
||||
|
||||
### The `state_override` Message
|
||||
|
||||
1. type: 65527 (`state_override`)
|
||||
2. data:
|
||||
* [`u32`:`block_day`]
|
||||
* [`u32`:`local_updates`]
|
||||
* [`u32`:`remote_updates`]
|
||||
* [`signature`:`local_sig_of_remote`]
|
||||
|
||||
After receiving a `state_override`, at any point a CLIENT may send a `state_update` that
|
||||
matches the `last_cross_signed_state` implied by the `state_override` parameters. That will
|
||||
put the channel back in an active state.
|
||||
|
||||
### Optional branding
|
||||
|
||||
Channels can be "branded", i.e. they can have a URL for human contact, a color and an image
|
||||
logo.
|
||||
|
||||
Upon establishing a connection to a HOST, a CLIENT can at anytime send a `ask_branding_info`
|
||||
message and a HOST may or may not reply with a `hosted_channel_branding` message.
|
||||
|
||||
### The `ask_branding_info` Message
|
||||
|
||||
1. type: 65511 (`ask_branding_info`)
|
||||
2. data:
|
||||
* [`chain_hash`:`chain_hash`]
|
||||
|
||||
### The `hosted_channel_branding` Message
|
||||
|
||||
1. type: 65525 (`hosted_channel_branding`)
|
||||
2. data:
|
||||
* [`3*byte`:`rgb_color`]
|
||||
* [`bool`:`has_png`]
|
||||
* [`if has_png: u16`:`len`]
|
||||
* [`len*byte`:`png_icon`]
|
||||
* [`u16`:`len`]
|
||||
* [`len*byte`:`contact_info`]
|
||||
|
||||
The `png_icon` must have at most 65535 bytes, and `contact_info` must be a valid URL.
|
||||
|
||||
## Rationale
|
||||
|
||||
The protocol for hosted channels was created based on real-world experience maintaining
|
||||
the first standalone Lightning mobile wallet, [BLW][blw], and improved upon the
|
||||
[initial version of the protocol][rfc1] that was deployed on that in 2019.
|
||||
|
||||
It introduces some new messages with numbers picked from the end of the range of
|
||||
available numbers and a set of messages related to HTLC adding and removing that are
|
||||
exactly like their BOLT equivalents, but wrapped so they don't interfere with the normal
|
||||
protocol and can be implemented on plugins that allow custom messages to be sent and
|
||||
received from nodes like Eclair, CLN and LND.
|
||||
|
||||
## Universality
|
||||
|
||||
Most nodes are probably not interested in using hosted channels, but that is fine since
|
||||
for the protocol to be useful we only ever need two parties that are interested in
|
||||
establishing such a channel to support it, and they connect to each other directly.
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
This does not have backwards compatibility concerns.
|
||||
|
||||
## Reference Implementations
|
||||
|
||||
* Simple Bitcoin Wallet (client): <https://github.com/btcontract/wallet>
|
||||
* Eclair Plugin (host): <https://github.com/btcontract/plugin-hosted-channels>
|
||||
* IMMORTAN (client): <https://github.com/fiatjaf/immortan>
|
||||
* Poncho (host): <https://github.com/fiatjaf/poncho>
|
||||
* scoin (types and codecs): [https://github.com/fiatjaf/scoin](https://github.com/fiatjaf/scoin/blob/master/shared/src/main/scala/hc/HostedChannelCodecs.scala)
|
||||
|
||||
[blw]: https://archive.is/iMVJj
|
||||
[rfc1]: https://github.com/btcontract/hosted-channels-rfc/tree/b9d53d5ec9e5238273cead742730cf15824ef48f
|
||||
[bolt01]: https://github.com/lightning/bolts/blob/master/01-messaging.md
|
||||
[bolt02]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md
|
||||
[bolt02-scriptpubkey]: https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#closing-initiation-shutdown
|
||||
[hosted_sighash]: https://github.com/fiatjaf/scoin/blob/315be232a70e9a9caa648ac384b679e6eb563ad7/shared/src/main/scala/hc/HostedChannelMessages.scala#L77-L117
|
||||
[error]: https://github.com/lightning/bolts/blob/master/01-messaging.md#the-error-and-warning-messages
|
||||
[update_add_htlc]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc
|
||||
[update_fulfill_htlc]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc
|
||||
[update_fail_htlc]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc
|
||||
[update_fail_malformed_htlc]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc
|
Loading…
Reference in New Issue
Block a user