diff --git a/README.md b/README.md index e2a1c45..302e619 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,4 @@ For more detail on the process, please read [bLIP-0001](./blip-0001.md) and | [51](./blip-0051.md) | LSPS1: Channel Requests | Severin Bühler | Active | | [52](./blip-0052.md) | LSPS2: JIT Channel Negotiation | ZmnSCPxj jxPCSnmZ | Active | | [55](./blip-0055.md) | LSPS5: Webhook Registration | ZmnSCPxj jxPCSnmZ | Active | +| [70](./blip-0070.md) | RGB Asset Support | will-bitlightlabs | Draft | diff --git a/blip-0002.md b/blip-0002.md index f0e2937..24ddae1 100644 --- a/blip-0002.md +++ b/blip-0002.md @@ -32,8 +32,13 @@ network split. * [Messages](#messages) * [TLV fields in BOLT messages](#tlv-fields-in-bolt-messages) * [`init`](#init) - * [`ping`](#ping) + * [`open_channel`](#open_channel) + * [`open_channel2`](#open_channel2) * [`update_add_htlc`](#update_add_htlc) + * [`channel_announcement`](#channel_announcement) + * [`channel_update`](#channel_update) + * [`ping`](#ping) + * [`payment_onion_payload`](#payment_onion_payload) * [Onion Messages](#onion-messages) ### Feature bits @@ -53,6 +58,7 @@ bLIPs may reserve feature bits by adding them to the following table: | 260/261 | `htlc_endorsement` | This node forwards experimental htlc endorsement signals | N | | [bLIP 4](./blip-004.md) | | 262/263 | `bolt11_blinded_path` | This invoice may contain a new blinded path tagged field | I | `option_route_blinding` | [bLIP 39](./blip-0039.md) | | 729 | `option_supports_lsps` | This node supports LSPS protocol(s) | IN | | [bLIP 50](./blip-0050.md) | +| 826/827 | `rgb_channel` | RGB colored channel support | INCT | | [bLIP 70](./blip-0070.md) | ### Messages @@ -98,12 +104,45 @@ The following table contains extension tlv fields for the `init` message: |-------|-----------------------------|--------------------------------| | 65536 | `tlv_field_name` | Link to the corresponding bLIP | +#### `open_channel` + +The following table contains extension tlv fields for the `open_channel` message: + +| Type | Name | Link | +|--------|-----------------------------|--------------------------------| +| 827167 | `rgb_context_data` | [bLIP 70](./blip-0070.md) | + +#### `open_channel2` + +The following table contains `opening_tlvs` fields for the `open_channel2` message: + +| Type | Name | Link | +|--------|-----------------------------|--------------------------------| +| 827167 | `rgb_context_data` | [bLIP 70](./blip-0070.md) | + +#### `channel_announcement` + +The following table contains trailing TLV fields appended after the defined fields in the `channel_announcement` message: + +| Type | Name | Link | +|--------|-----------------------------|--------------------------------| +| 827167 | `rgb_asset_id` | [bLIP 70](./blip-0070.md) | + +#### `channel_update` + +The following table contains trailing TLV fields appended after the defined fields in the `channel_update` message: + +| Type | Name | Link | +|--------|-----------------------------|--------------------------------| +| 827167 | `rgb_htlc_maximum` | [bLIP 70](./blip-0070.md) | + #### `payment_onion_payload` The following table contains extension tlv fields for the `payment_onion_payload` message: | Type | Name | Link | |-------------|-----------------------------|--------------------------------| +| 827167 | `rgb_amount_to_forward` | [bLIP 70](./blip-0070.md) | | 7629169 | `podcasting_2_0` | [bLIP 10](./blip-0010.md) | | 5482373484 | `keysend_preimage` | [bLIP 3](./blip-0003.md) | @@ -113,8 +152,9 @@ The following table contains extension tlv fields for the `update_add_htlc` mess | Type | Name | Link | |--------|-----------------------------|--------------------------------| -| 106823 | `endorsed` | [bLIP 4](./blip-0004.md) | | 65537 | `extra_fee` | [bLIP 25](./blip-0025.md) | +| 106823 | `endorsed` | [bLIP 4](./blip-0004.md) | +| 827167 | `rgb_amount` | [bLIP 70](./blip-0070.md) | #### `ping` diff --git a/blip-0070.md b/blip-0070.md new file mode 100644 index 0000000..86978ce --- /dev/null +++ b/blip-0070.md @@ -0,0 +1,266 @@ +``` +bLIP: 70 +Title: RGB Asset Support for Lightning Network +Status: Draft +Author: will-bitlightlabs +Created: 2026-03-27 +License: CC0 +``` + +## Abstract + +This bLIP defines protocol extensions for carrying RGB colored assets over Lightning +Network channels. It introduces a feature bit for RGB channel negotiation and TLV +fields in wire messages and onion payloads for asset metadata exchange. Standard +Lightning nodes that do not support this extension safely ignore all additions +following the "it's ok to be odd" convention. + +## Copyright + +This bLIP is licensed under the CC0 license. + +## Motivation + +The Lightning Network currently only supports BTC payments. However, the RGB +protocol enables issuance and transfer of arbitrary assets on Bitcoin using +client-side validation. Integrating RGB with Lightning allows these assets to +be transferred instantly over payment channels. + +Without standardized protocol extensions, RGB-enabled Lightning implementations +would use ad-hoc wire format modifications that break interoperability with +standard nodes. This bLIP provides a minimal, backward-compatible extension +that allows RGB and non-RGB nodes to coexist on the same network. + +## Rationale + +### Why a feature bit instead of implicit detection + +Explicit feature bit negotiation (bit 826 in `channel_type`) ensures that both +peers understand and agree on the RGB channel semantics before any commitment +transaction is built. Without this, a peer might accept an RGB channel without +understanding the OP_RETURN output in commitment transactions, leading to +signature mismatches. + +### Why 827167 for TLV type + +Using a value derived from SLIP-0044 provides clear provenance and avoids +collision with existing bLIP registrations. The odd parity ensures standard +nodes ignore unknown fields per BOLT #1. + +### Why trailing TLV for gossip messages + +`channel_announcement` and `channel_update` use a different serialization +pattern than other BOLT messages — they do not have a TLV extension stream. +Instead, any future fields are appended as trailing data after the defined +fields. RGB fields are appended as TLV in this trailing region, which is +covered by the message signature (BOLT #7: signature covers all bytes from +the message body through the end of the message). + +## Specification + +### Feature Bit + +| Bits | Name | Description | Context | Dependencies | +|------|------|-------------|---------|--------------| +| 826/827 | `rgb_channel` | RGB colored channel support | INCT | | + +Bit 827 (odd/optional) is set in `init` and `node_announcement` to advertise RGB +support. Bit 826 (even/required) is set in `channel_type` to negotiate a specific +RGB channel. Bit 827 (odd/optional) is set in `channel_announcement` features to +mark a channel as RGB-capable in gossip. + +### Wire Message TLV Fields + +#### `open_channel` + +1. `tlv_stream`: `open_channel_tlvs` +2. types: + 1. type: 827167 (`rgb_context_data`) + 2. data: + - [`...*byte`:`data`] + +#### `open_channel2` + +1. `tlv_stream`: `opening_tlvs` +2. types: + 1. type: 827167 (`rgb_context_data`) + 2. data: + - [`...*byte`:`data`] + +`rgb_context_data` is an opaque byte blob. Implementations SHOULD encode it as +a UTF-8 consignment endpoint URL. Supported URL schemes: +- `https:///` — HTTP(S) endpoint for fetching RGB consignment +- `http:///` — HTTP endpoint +- `file://` — local filesystem (testing only) + +The URL MAY contain a `{txid}` placeholder, which the receiver replaces with +the funding transaction ID. Example: `https://proxy.example.com/consignment/{txid}` + +The writer: +* MUST set `rgb_context_data` when opening an RGB colored channel +* MUST NOT set `rgb_context_data` for pure BTC channels +* SHOULD encode the value as a valid UTF-8 URL with a recognized scheme + +The receiver: +* If `rgb_context_data` is present but the receiver does not support `rgb_channel`: + * MUST ignore the TLV field (odd type rule) + * MUST NOT treat the channel as an RGB channel +* If the data cannot be parsed as valid UTF-8 or contains an unrecognized URL + scheme, the receiver SHOULD silently ignore the field and proceed without + prefetching the RGB consignment + +#### `update_add_htlc` + +1. `tlv_stream`: `update_add_htlc_tlvs` +2. types: + 1. type: 827167 (`rgb_amount`) + 2. data: + - [`u64`:`amount`] + +The writer: +* MUST set `rgb_amount` to the RGB asset amount carried by this HTLC +* MUST NOT set `rgb_amount` for pure BTC HTLCs + +The receiver: +* If `rgb_amount` is present but the receiver does not support `rgb_channel`: + * MUST ignore the TLV field +* If `rgb_amount` is present and the receiver supports `rgb_channel`: + * MUST process the HTLC as carrying the specified RGB asset amount + +#### `channel_announcement` (trailing TLV) + +1. `tlv_stream`: appended as trailing data after the defined fields +2. types: + 1. type: 827167 (`rgb_asset_id`) + 2. data: + - [`32*byte`:`contract_id`] + +`rgb_asset_id` is a 32-byte RGB contract identifier (`ContractId` in RGB v0.12). + +The writer: +* MUST set `rgb_asset_id` to the 32-byte RGB contract identifier for an RGB channel +* MUST NOT set `rgb_asset_id` for pure BTC channels +* MUST set feature bit 827 (odd) in the `features` field + +The receiver: +* SHOULD verify the field is exactly 32 bytes; if the length does not match, + the field SHOULD be treated as invalid and the channel SHOULD NOT be + considered for RGB routing +* MAY use `rgb_asset_id` for RGB-aware route selection +* This field is covered by the `channel_announcement` signature + +#### `channel_update` (trailing TLV) + +1. `tlv_stream`: appended as trailing data after the defined fields +2. types: + 1. type: 827167 (`rgb_htlc_maximum`) + 2. data: + - [`u64`:`amount`] + +The writer: +* MUST set `rgb_htlc_maximum` to the maximum HTLC amount in RGB asset units +* MUST NOT set `rgb_htlc_maximum` for pure BTC channels + +The receiver: +* MAY use `rgb_htlc_maximum` for RGB-aware route capacity checks +* This field is covered by the `channel_update` signature + +### Onion Payload TLV Field + +#### Per-hop `payload` (BOLT #4) + +1. `tlv_stream`: `payload` +2. types: + 1. type: 827167 (`rgb_amount_to_forward`) + 2. data: + - [`u64`:`amount`] + +The writer: +* MUST set `rgb_amount_to_forward` to the RGB asset amount the next hop should forward +* For the final hop, this is the amount the receiver should claim + +The receiver: +* If forwarding: MUST set `rgb_amount` in the outgoing `update_add_htlc` to this value +* If final hop: MUST verify the received RGB amount matches expectations + +Note: This TLV is encoded within the encrypted onion payload. Intermediate nodes +that do not support RGB cannot read or modify this value. + +### TLV Type Selection + +All TLV fields use type **827167** (`0x000C9F1F`), derived from +[SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) RGB on +Bitcoin (testnet) coin type. Feature bit 826/827 echoes the same SLIP-0044 prefix. + +BigSize encoding: `fe 00 0c 9f 1f` (5 bytes). Same cost as other bLIP TLV types +(e.g., `endorsed` at 106823, `extra_fee` at 65537). + +### Commitment Transaction + +When `channel_type` includes the `rgb_channel` feature bit (826), the commitment +transaction base weight includes an additional **172 weight units** for an +OP_RETURN output used by the RGB protocol for deterministic Bitcoin commitment +(DBC). This ensures both parties agree on fee calculations. + +#### OP_RETURN Output Format + +The OP_RETURN output is 43 serialized bytes × 4 = 172 weight units: + +``` + 8 bytes output value (always 0) + 1 byte scriptPubKey length varint (0x22 = 34) + 1 byte OP_RETURN opcode (0x6a) + 1 byte OP_PUSHBYTES_32 opcode (0x20) + 32 bytes MPC commitment (mpc::Commitment, fixed 32 bytes) + ────── + 43 bytes × 4 = 172 weight units +``` + +#### Placement + +The OP_RETURN output is always placed at the **last output index**, after all +standard outputs (to_local, to_remote, HTLCs, anchors) have been constructed +and sorted per BIP 69. Both holder and counterparty commitment transactions +include this output. + +## Universality + +This feature is NOT intended to be universal. RGB asset support is an +application-layer extension for nodes that choose to participate in the RGB +ecosystem. Standard Lightning nodes (CLN, LND, Eclair) can safely ignore all +RGB extensions: + +- Unknown odd feature bits in `init` are ignored (BOLT #1) +- Unknown odd feature bits in `channel_announcement` are ignored (BOLT #7) +- Unknown odd TLV fields in wire messages are ignored (BOLT #1) +- Onion payload fields are encrypted and only visible to intended recipients +- Gossip messages with RGB data are relayed unmodified (signature covers all trailing data) + +A node that does not support RGB will never accidentally open an RGB channel, +because `channel_type` negotiation requires explicit agreement (BOLT #2). + +## Backwards Compatibility + +All extensions use odd-numbered identifiers: + +| Extension | Value | Parity | Standard node behavior | +|-----------|-------|--------|----------------------| +| Feature bit | 827 (in init/node/channel) | odd | Safely ignored | +| Feature bit | 826 (in channel_type) | even | Channel type rejected if unknown — correct behavior | +| TLV type | 827167 | odd | Safely ignored | + +There are no backwards compatibility issues for standard Lightning nodes. The +extensions are fully additive and do not modify any existing BOLT behavior. + +For RGB-enabled nodes, the commitment transaction includes an OP_RETURN output +(+172 weight units). This is negotiated via `channel_type` feature bit 826, +ensuring both peers use the same fee calculation. + +## Reference Implementation + +A reference implementation based on LDK (rust-lightning) is under development by +Bitlight Labs. The implementation will be made available upon public release. + +TLV type and feature bit values are derived from +[SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) RGB +coin type registration (827166/827167) by Dr. Maxim Orlovsky.