diff --git a/blip-0002.md b/blip-0002.md index 1db70e4..2375bee 100644 --- a/blip-0002.md +++ b/blip-0002.md @@ -45,13 +45,14 @@ Custom feature bits used in the `I` [Bolt 11](https://github.com/lightning/bolts 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) | -| 256/257 | `hosted_channels` | This node accepts requests for hosted channels | IN | | [bLIP 17](./blip-0017.md) | -| 258/259 | `dns_resolver` | This node accepts DNSSEC proof requests | N | | [bLIP 32](./blip-0032.md) | -| 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) | +| 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) | +| 258/259 | `dns_resolver` | This node accepts DNSSEC proof requests | N | | [bLIP 32](./blip-0032.md) | +| 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) | +| 270/271 | `pluggable_channel_factories` | This node supports channels inside channel factories | I | | [bLIP 56](./blip-0056.md) | ### Messages @@ -75,6 +76,7 @@ bLIPs may create new messages and reserve their type in the following table: | 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) | +| 32800 | `factory_message_id` | [bLIP 56](./blip-0056.md) | ### TLV fields in BOLT messages @@ -114,6 +116,14 @@ The following table contains extension tlv fields for the `update_add_htlc` mess | 106823 | `endorsed` | [bLIP 4](./blip-0004.md) | | 65537 | `extra_fee` | [bLIP 25](./blip-0025.md) | +#### `open_channel` + +The following table contains extension tlv fields for the `open_channel` message: + +| Type | Name | Link | +|--------|-----------------------------|--------------------------------| +| 65600 | `channel_in_factory` | [bLIP 56](./blip-0056.md) | + #### `ping` The following table contains extension tlv fields for the `ping` message: diff --git a/blip-0056.md b/blip-0056.md new file mode 100644 index 0000000..e71c49e --- /dev/null +++ b/blip-0056.md @@ -0,0 +1,965 @@ +``` +bLIP: TBD +Title: Pluggable Channel Factories +Status: Draft +Author: ZmnSCPxj jxPCSnmZ +Created: 2024-11-11 +* Post-History: https://delvingbitcoin.org/t/pluggable-channel-factories/1252 +License: CC0 +``` + +Abstract +======== + +Pluggable channel factories are a way of modifying existing Lightning Network +node software to allow them to manage channel state and payment forwarding +state for channels hosted inside channel factories. +The existing node software would only be aware that the channel is hosted inside +*some* channel factory, while additional software could be connected to it +("plugged in" via some plugin or equivalent mechanism, such as side daemons in +LND or trait-implementing client structures in LDK) that handles the details of the +channel factory itself. +This neatly divides responsibility: existing node software handles in-channel +state and payment forwarding, while the "plugin" software handles the channel +factory state. + +Copyright +========= + +This bLIP is licensed under CC0. + +Rationale +========= + +Channel factories are multiparty (N > 2) offchain constructions that themselves +contain multiple 2-party offchain channels. + +For the most part, 2-party channels, whether hosted directly from a UTXO confirmed +on the blockchain, or inside a channel factory, work the same, and the messages +and transactions involved would be largely identical. + +We can therefore consider that existing software that handles channel state and +payment forwarding can be minimally modified to support channels that are inside a +channel factory instead of on the blockchain. + +In addition, many existing Lightning Network node software, such as CLN, Eclair, +LND, and LDK, all have mechanisms by which additional code can be attached to them +to modify their operation. +CLN and Eclair have plugins, LND has side daemons, and LDK has trait-implementing +client structures. +Thus, it would be conceivable for these node software to expose additional +interfaces to their plugin (or equivalent) interfaces, where the plugin can manage +state for a channel factory, and the actual node software manages the state for +the channels inside the channel factory. + +This bLIP thus describes a common protocol for node software to agree that some +channel being managed with a peer is inside a channel factory, and for operations +that change the capacity of that channel. +It also describes a protocol that the factory protocol plugin can use to tunnel +its messages for other participants in the same factory instance. + +Glossary +======== + +* Channel Factory Protocol Identifier (`factory_protocol_id`) - a 256-bit + identifier that identifies the protocol of the channel factory. + - It is recommended, but not required, that the `factory_protocol_id` be + the SHA-256 of the concatenation of the channel factory protocol name and + major version. +* Channel Factory Instance Identifier (`factory_instance_id`) - a 256-bit + identifier that identifies a specific instance of a channel factory + protocol. +* Channel Factory Early Warning Time (`factory_early_warning_time`) - a 16-bit + number, specified per instance of a channel factory, that specifies to the + node software how early to warn the channel factory plugin that an HTLC is + about to time out. +* Channel Factory Sub-message Identifier (`factory_submessage_id`) - a 16-bit + message identifier, in a separate namespace from the common BOLT messages, + for all messages related to the pluggable channel factory protocol. + The "it's okay to be odd" rule also applies to this message identifier. +* Pluggable Channel Factory Message (`factory_message_id`, 32800) - a 16-bit + message identifier, with the value 32800, in the namespace of the common + BOLT messages. + All messages related to the pluggable channel factory protocol share a + single `factory_message_id`, and are differentiated by the + `factory_submessage_id`. +* Pluggable Channel Factory Feature Bit + (`pluggable_channel_factories`, 271) - a feature bit, + index 271, in the namespace of the common BOLT + feature bits. + A node which advertises this feature bit in `node_announcement` and + `init` supports the pluggable channel factory protocol described in this + document. +* Channel Factory Plugin - some code that handles channel factory concerns + for a specific `factory_protocol_id`. + +Overview +======== + +This protocol adds the following extensions: + +* Adds a feature bit, `pluggable_channel_factories` + (271), that indicates + support for this protocol. +* Adds a TLV, `channel_in_factory` (65600), to the + `open_channel` message. +* Slightly modifies the timing of the `channel_ready` + message if the above TLV is included in + `open_channel`. +* Adds a new message, `factory_message_id` (32800), + that is used for all messages in this protocol. +* Reuses most of the splicing flow (`stfu` message, + the `batch` TLV of `commitment_signed`, and + `next_funding_txid` TLV of `channel_reestablish`) + for channel factory state changes. + +Channel Factory Plugin +====================== + +***How*** the base node software talks to the channel +factory plugin is not specified by this protocol. +It depends entirely on the actual node software. + +The node software MAY implement a particular channel +factory protocol "built in", i.e. without implementing +some plugin interface, and implementing all the code +necessary for that particular channel factory protocol +to work. +However, in the rest of this document, I will describe +the "base" node software as checking with its channel +factory plugin. +This means that the base node software checks if there +is some code (built in, or connected via some plugin +or equivalent interface) that implements a particular +`factory_protocol_id`, and then passes as much +information to that code as possible, which then +should indicate whether validation passes or fails. + +The "base" node software is something like CLN, LND, +LDK, Eclair, etc., which handles the in-channel states +as well as changing the channel funding outpoint +whenever the channel factory itself changes state. +The base node software has to implement the protocol +described in this document. +The "channel factory plugin" is additional code, which +may or may not be built-in to the base node software, +which directly handles the channel factory state. + +In this document, validation requirements are +indicated for the "base" node software. +Some additional validation would then be delegated +to the channel factory plugin, and specified as such, +but the specific validation details would vary +depending on the actual channel factory protocol, +and are not in the scope of this document. + +New `open_channel` TLV (`channel_in_factory`, 65600) +==================================================== + +A new TLV for `open_channel` indicates that the channel +to be opened is actually inside a channel factory, +with the factory protocol indicated, as well as the +specific instance of the factory. +It also indicates the "early warning time" that the +base node software needs to warn its instance of the +factory plugin, before an HTLC times out. + +1. types: + 1. type: 65600 (`channel_in_factory`) + 2. data: + * [`32 * u8`: `factory_protocol_id`] + * [`32 * u8`: `factory_instance_id`] + * [`u16`: `factory_early_warning_time`] + +Requirements: + +The sender: + +* MUST NOT include the `channel_in_factory` TLV, unless + all of the below are true: + - The peer advertised support for the specified + `factory_protocol_id`. + - The channel factory plugin (or equivalent) specified + that this TLV is to be included, and specified the + information `factory_protocol_id`, + `factory_instance_id`, and `factory_early_warning_time`. +* MUST indicate `option_zeroconf` for the channel if it + includes `channel_in_factory` TLV. + +The receiver, if it receives an `open_channel` with a +`channel_in_factory` TLV: + +* MUST validate that it advertised support for the specified + `factory_protocol_id`. +* MUST check, with its channel factory plugin (or equivalent) + that the `factory_instance_id` and `factory_early_warning_time`, + as well as the other fields of `open_channel`, are + valid for the channel being opened. + - If the channel factory plugin indicates validation + failure, MUST reject the channel by sending + `error`. +* MUST check that `option_zeroconf` channel type is set. +* MUST fail the channel if the above validation fails. +* SHOULD accept the channel otherwise. + +If an openv1 channel open is started with `channel_in_factory` +TLV, the channel opening flow is subsequently modified: + +* Both peers MUST save the contents of `channel_in_factory` + in persistent storage, associated with the channel, until + the channel can be safely forgotten. +* `funding_created`: + * The sender MUST use a `funding_txid` and + `funding_output_index` specified by the channel factory + plugin (or equivalent). + * The receiver MUST check, with its channel factory plugin + (or equivalent) that the `funding_txid` and + `funding_output_index` are valid for the specific channel + that is being constructed. +* `channel_ready`: + * Both peers MUST check, with their respective + channel factory plugin (or equivalent) *when* the + `channel_ready` message is to be sent. + Even if `option_zeroconf` is required to be set, + the base node software must wait for the channel + factory plugin to complete setting up of the + channel factory state to include the new channel, + before accepting transfers on that channel. +* The fundee MUST NOT forget the channel even if the channel + funding transaction is not confirmed within 2016 blocks. +* The funder MUST NOT broadcast the channel funding + transaction. + - The base node software of the funder node should + not have access to this transaction, and even if + it does, should not broadcast it itself; broadcast + of any transactions would need to be initiated by + the channel factory plugin (or equivalent). + +In addition, if a channel was opened with +`channel_in_factory`, the following additional restrictions +on update messages exist: + +* `update_add_htlc`: + * The sender MUST set `cltv_expiry` to greater than or + equal to the current block height plus + `factory_early_warning_time` plus 1. + - If the sender would fail this check due to a + forwarding request, SHOULD fail the forward + with `expiry_too_soon`. + * The receiver MUST check that `cltv_expiry` is greater + than or equal to the current block height plus + `factory_early_warning_time` plus 1. + - if this validation fails, MUST send `error` and + fail the channel. + +If a channel was opened with `channel_in_factory`: + +* If the node has a pending offered HTLC on the + channel, and the current block height plus + `factory_early_warning_time` is greater than or + equal to the `cltv_expiry` of the HTLC, it MUST + raise an ignorable event to the channel factory + plugin regarding this early warning of an impending + HTLC timeout. +* If the node would fail the channel, or otherwise + close the channel (such as by a closure request by + the human operator), it MUST raise an ignorable event + to the channel factory plugin. + - The plugin SHOULD broadcast any parent transactions + as well as the funding transaction for the channel, + but MAY elect not to do so depending on the + channel factory protocol. + - The base node software MUST persist the failed + state and treat the channel as closed, but remember + its latest signed commitment transactions, until + the base node software sees the funding transaction + confirmed, or until the plugin indicates to + forget the channel completely. + - On node restart, the base node software MUST + raise the same event to the relevant plugin, as + long as it has a closed in-factory channel where + it has not seen any funding transaction confirmed, + and which the plugin has not indicated to forget. + - The base node software MUST NOT broadcast the + latest commitment transaction until it has seen + one of the possible funding transactions confirmed. +* The channel factory plugin MAY indicate to completely + forget about the channel at any time, including after + the base node software indicates it will fail or + close the channel. + - The base node software MUST treat the forgotten + channel as successfully closed with deep + confirmation of the closure, even if it did not + successfully broadcast and confirm a commitment + transaction for the channel. + - The base node software MAY remember the previous + existence of the forgotten channel for reporting + to the human operator, and SHOULD forget any + cryptographic data, such as historical HTLCs, + revocation keys, and commitment transaction + signatures, that it would normally forget about a + long-closed channel. + - **Rationale** A channel factory protocol may itself + have a punishment mechanism (outside of the BOLT + punishment mechanism) where a hosted channel + is invalidated, with all in-channel funds sent as + compensation to the attempted theft victim. + In such cases, the state of the channel would + become moot, and persisted state about it can be + deleted to free up space. + +If any channel of a node was opened with +`channel_in_factory`: + +* When creating an invoice, SHOULD add, to its + expected `min_final_cltv_expiry_delta`, the highest + `factory_early_warning_time` amongst all active + non-`shutdown` channels with sufficient inbound + liquidity (channels that were not opened with + `channel_in_factory` consider their + `factory_early_warning_time` as 0), or any higher + number. +* When sending a payment, SHOULD ensure that, if it + uses a `channel_in_factory` channel as the first + hop, it sends an HTLC with timeout of at least + `factory_early_warning_time` plus current + blockheight plus the second hop's `cltv_delta` + (or `min_final_cltv_expiry_delta` if the direct + peer is the final payee). + +New `factory_message_id` Message Type +===================================== + +A new `factory_message_id` (32800) is used to multiplex all +messages related to pluggable channel factories: + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `factory_submessage_id`] +3. `tlv_stream` : `factory_message_tlvs` +4. types: depends on `factory_submessage_id` + +The subsections below describe the valid values of +`factory_submessage_id` and their respective TLVs. + +> **Rationale** A single message ID is allocated +> so that future extensions to this protocol can +> use the full 16 bits of the `factory_submessage_id` +> without having to continuously add to blip-002. + +The `supported_factory_protocols` Message +----------------------------------------- + +The `supported_factory_protocols` (`2`) message informs +the peer of the `factory_protocol_id`s a node supports. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x0002` (`supported_factory_protocols`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types + 1. type: 512 (`factory_protocol_ids_tlv`) + 2. data: + * [`... * 32 * u8` : `supported_factory_protocol_ids`] + +Requirements: + +Nodes: + +* MUST send this message after receiving `init` message + from a peer, if that peer indicates support for + pluggable channel factories feature bit + (`pluggable_channel_factories`, 271). + +The sender: + +* MUST include `factory_protocol_ids_tlv`. +* MAY set `factory_protocol_ids_tlv` to 0 length, + indicating it does not actually support any actual + channel factory protocols. + +The receiver: + +* MUST check that `factory_protocol_ids_tlv` exists + and has length that is a multiple of 32 bytes, + including 0. + - If not, MUST send `warning` and close the + connection. +* SHOULD store the union of its set of supported + `factory_protocol_id`s and the set sent by the peer, + and make this available to any channel factory plugin + (or equivalent) it has. + +The `factory_piggyback` Message +------------------------------- + +The `factory_piggyback` (`4`) message is intended to +be used by the channel factory plugin (or equivalent) +to directly communicate with its counterpart on the +peer. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x0004` (`factory_piggyback`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types: + 1. type: 0 (`factory_protocol_id_tlv`) + 2. data: + * [`32 * u8` : `factory_protocol_id`] + 3. type: 1024 (`factory_piggyback_payload_tlv`) + 4. data: + * [`...*byte`: `factory_piggyback_payload`] + +Requirements: + +The sender: + +* MUST NOT send this message unless indicated by the + channel factory plugin (or equivalent). +* MUST include `factory_protocol_id_tlv` and + `factory_piggyback_payload_tlv`. +* MUST set `factory_protocol_id` to a value that + is advertised by itself *and* by the receiver in + their respective `supported_factory_protocols`. + - SHOULD consider it an error of the plugin if the + plugin indicates sending a message to a peer that + does not support its indicated + `factory_protocol_id`. + +The receiver: + +* MUST check that `factory_protocol_id_tlv` and + `factory_piggyback_payload_tlv` are included. +* MUST check that it advertised support of the + indicated `factory_protocol_id`. +* If the above validation fails, MUST send + `warning` and close the connection. + +On receiving and validating this message, the base +node software SHOULD pass it to the channel factory +plugin (or equivalent), which then interprets the +`factory_piggyback_payload` depending on the +channel fatory protocol. +The exact format of the data inside the payload is +outside the scope of this document. + +The Channel Factory State Change Flow +------------------------------------- + +The state of the channel factory layer can change, +and this change in state is likely to cause the +funding transactions of channels hosted inside it to +also change, whether or not the channels change +their capacity. + +The channel factory state change flow co-opts some +steps of the onchain splicing flow (feature 62/63, +[BOLTs pull request 1160][]). + +[BOLTs pull request 1160]: https://github.com/lightning/bolts/pull/1160 + +The overall flow of splicing is below: + +1. The channel must be quiesced with [the `stfu` + message](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#stfu). +2. A peer sends `splice_init`, and the peers exchange + `tx_add_input` and `tx_add_output` messages until + they are satisfied and end with `tx_complete`, + then they exchange an initial `commitment_signed` + for the post-splice state. +3. The peers sign the splice transaction with + `tx_signature`. +4. The peers then resume the channel. + In this intermediate state, the peers exchange + multiple `commitment_signed` messages for each + channel state update, using the `batch` TLV, + one for the pre-splice state and one for each + valid post-splice state. +5. The splice transaction confirms deeply enough, + and the peers exchange `splice_locked`. +6. The channel returns to the "normal" state where + each channel state only requires one + `commitment_signed` message without `batch` TLV. + +The flow for changing a channel factory state (which +MAY change the capacity of channels) replaces the +above flow with some factory messages: + +1. The channel must be quiesced with [the `stfu` + message](https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#stfu). +2. A peer sends `factory_change_init` containing + the change in capacity of the channel, then + the peers agree on the new funding transaction + outpoint via `factory_change_funding`, + then they exchange an initial + `commitment_signed` for the post-change state. +3. The peers arrange to sign the next channel factory + state (they need not sign immediately, but they do + need to start signalling each other to do so). + This may require piggybacked messages to exchange + signatures for the new factory state, depending + on the channel factory details. + The peers then exchange + `factory_change_continue` messages containing the + transaction ID and output number for the hosted + channel. +4. The peers then resume the channel. + In this intermediate state, the peers exchange + multiple `commitment_signed` messages for each + channel state update, using the `batch` TLV, + one for the pre-factory-change state and one for + each valid post-factory-change state. +5. The peers make the old channel factory state + invalid and the new channel factory state valid. + The peers then exchange `factory_change_locked` + messages. +6. The channel returns to the "normal" state where + each channel state only requires one + `commitment_signed` message without `batch` TLV. + +Co-opting the *channel*-level onchain splicing +flow does not preclude *factory*-level onchain +splicing. +If the factory itself implements splicing (including +splicing in and out entire channels or even +participants) then the factory would need to +construct *some* change in the in-factory state, +which, at the channel level, can then use this +flow of changing the hosting factory state. + +### The `factory_change_init` and `factory_change_ack` Messages + +The `factory_change_init` (`6`) message signals +the beginning of the change in the channel factory +state. +The `factory_change_ack` (`8`) message signals +that the other side agrees to this change. +These two messages also indicate the new funding +outpoint to be used after the change. + +Both messages use the same `factory_change_tlv`, +and optionally may include a piggybacked payload +via `factory_piggyback_payload_tlv`. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x0006` (`factory_change_init`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types: + 1. type: 1024 (`factory_piggyback_payload_tlv`) + 2. data: + * [`...*byte`: `factory_piggyback_payload`] + 3. type: 1536 (`factory_change_tlv`) + 4. data: + * [`channel_id` : `channel_id`] + * [`s64` : `funding_contribution_satoshis`] + * [`point` : `funding_pubkey`] + +Requirements: + +The sender: + +* MUST NOT send `factory_change_init` if the channel + is not quiescent. +* MUST NOT send `factory_change_init` if it is not + the quiescence initiator. +* MUST NOT send `factory_change_init` before sending + `channel_ready`. +* MUST NOT send `factory_change_init` while another + factory-level change is being negotiated. +* MUST NOT send `factory_change_init` if another + factory-level change has been negotiated but + `factory_change_locked` has not been sent and + received. +* MUST NOT send `factory_change_init` if it has + sent `shutdown`. +* MUST NOT send `factory_change_init` unless indicated + by the channel factory plugin (or equivalent). +* MUST include `factory_piggyback_payload_tlv` if the + channel factory plugin indicated a piggybacked + payload, and MUST NOT include it otherwise. +* MUST always include `factory_change_tlv`. +* MUST set `channel_id` to a channel that was opened + with `channel_in_factory` TLV. +* MUST set `funding_contribution_satoshis` to 0, + positive, or a negative amount whose absolute + value is less than or equal to the sender's + current channel balance. + - SHOULD consider it an error of the plugin if the + plugin indicates using a negative + `funding_contribution_satoshis` whose absolute + value is greater than the sender's current channel + balance. + - MAY set this to 0 (unlike the splice case, where + it must be non-0). +* SHOULD use a different `funding_pubkey` than the + one used for the previous funding transaction. + +The receiver: + +* MUST check that the `factory_change_tlv` exists. + - If not, MUST send `warning` and close the + connection. +* MUST check that the `channel_id` refers to a channel + that was opened with `channel_in_factory`. + - If not, MUST send `warning` and close the + connection, or send `error` and fail the channel. +* MUST check that all the following conditions hold for + the channel; if any condition does not hold, it MUST + send a `warning` and close the connection, or send + `error` and fail the channel: + - The channel is quiescent. + - The sender is the quiescence initiator. + - No other factory-level change is being negotiated + for this channel. + - No other factory-level change has been negotiated + and not locked in yet. + - `funding_contribution_satoshis` is 0 or positive, + or if it is negative, has an absolute value that + is less than or equal to the sender's current + channel balance. +* MUST check, with its channel factory plugin (or + equivalent), that the `channel_id` and + `funding_contribution_satoshis` from the sender + are correct, as well as `factory_piggyback_payload` + if included, as per the channel factory protocol. + - If the channel factory plugin indicates validation + failure, MUST send `warning` and close the + connection or send `error` and fail the channel. +- MUST respond with `factory_change_ack` after the + channel factory plugin (or equivalent) has validated + the incoming message and indicates to respond, which + can be some time later. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x0008` (`factory_change_ack`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types: + 1. type: 1024 (`factory_piggyback_payload_tlv`) + 2. data: + * [`...*byte`: `factory_piggyback_payload`] + 3. type: 1536 (`factory_change_tlv`) + 4. data: + * [`channel_id` : `channel_id`] + * [`s64` : `funding_contribution_satoshis`] + * [`point` : `funding_pubkey`] + +Requirements: + +The sender: + +* MUST NOT send `factory_change_ack` unless the + peer sent `factory_change_init`. +* MUST NOT send `factory_change_ack` unless the + channel factory plugin (or equivalent) has + validated the `factory_change_init` from the + peer, and has indicated the + `funding_contribution_satoshis` and optionally + `factory_piggyback_payload` to include. +* MUST include `factory_piggyback_payload_tlv` if the + channel factory plugin indicated a piggybacked + payload, and MUST NOT include it otherwise. +* MUST always include `factory_change_tlv`. +* MUST set `funding_contribution_satoshis` to 0, + positive, or a negative amount whose absolute + value is less than or equal to the sender's + current channel balance. + - SHOULD consider it an error of the plugin if the + plugin indicates using a negative + `funding_contribution_satoshis` whose absolute + value is greater than the sender's current channel + balance. +* SHOULD use a different `funding_pubkey` than the + one used for the previous funding transaction. +* MUST, after sending `factory_change_ack`, wait for + the channel factory plugin (or equivalent) to + provide the funding transaction ID. + +The receiver: + +* MUST check that the `factory_change_tlv` exists. + - If not, MUST send `warning` and close the + connection. +* If it has not sent `factory_change_init`: + - MUST send a `warning` and close the connection, + or send an `error` and fail the channel. +* MUST check, with its channel factory plugin (or + equivalent), that the `channel_id` and + `funding_contribution_satoshis` from the sender + are correct, as well as `factory_piggyback_payload` + if included, as per the channel factory protocol, + and wait for the plugin to provide the funding + transaction ID. + - If the channel factory plugin indicates validation + failure, MUST send `warning` and close the + connection or send `error` and fail the channel. + +### The `factory_change_funding` Message + +The `factory_change_funding` (`10`) message is +exchanged by both peers to agree on the transaction +ID that the channel factory will use to host the +channel after the factory-level change. +It is sent after the `factory_change_init` and +`factory_change_ack` exchange. + +The channel factory plugin (or equivalent) may need to +initiate factory-level changes across multiple +channels, with multiple peers,for a single +factory-level change. +Once all the channels affected have had factory-level +changes initiated, the channel factory can determine +the new funding transactions needed for the affected +channels. +Then the plugin can inform the base node software +about the post-factory-level-change funding +transaction ID for each affected channel, which the +base node software counterchecks with the peer +base node software. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x000A` (`factory_change_funding`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types: + 1. type: 2560 (`factory_change_funding_tlv`) + 2. data: + * [`channel_id` : `channel_id`] + * [`sha256` : `funding_txid`] + * [`u16` : `funding_output_index`] + +Requirements: + +The sender: + +* MUST NOT send `factory_change_funding` until + after the `factory_change_ack` has been received + by itself (if it initiated quiescence) or sent + by itself (if it did not initiate quiescence). +* MUST NOT send `factory_change_funding` until + indicated by its channel factory plugin (or + equivalent), with the plugin also indicating + the `funding_txid` and `funding_output_index` + to use. +* MUST include `factory_change_funding_tlv`. + +The receiver: + +* MUST check that `factory_change_funding_tlv` + exists. + - If not, MUST send `warning` and close the + connection. +* MUST check that the given `funding_txid` + and `funding_output_index` are equal to what + its own channel factory plugin indicated or + will later indicate. + - If not, MUST send `warning` and close the + connection, or send `error` and fail the + channel. + +After it has both sent and received +`factory_change_funding`, the node: + +* MUST compute the channel balance for each + side by adding their respective + `funding_contribution_satoshis` to their + previous channel balance. + +### The `commitment_signed` Message + +After exchanging `factory_change_funding`, both +peers send `commitment_signed` to commit to the +factory-level change funding transaction (the +`funding_txid` sent in `factory_change_funding`) +by creating a commitment transaction spending the new +agreed-upon funding transaction output. + +The usual `commitment_signed` requirements apply +with the following additional requirements: + +The sender: + +* MUST create a commitment transaction that spends + the factory-level change funding transaction + output, and: + - Adds `funding_contribution_satoshis` from + `factory_change_init` and `factory_change_ack` + to the main balance of their respective sender. + - Uses the same feerate as the existing commitment + transaction. + - Uses the same `commitment_number` as the existing + commitment transaction. + - Does not set the `batch` field. +- MUST send signatures for pending HTLCs. +- MUST remember the details of the new funding + transaction output. + +The receiver: + +* MUST NOT respond with `revoke_and_ack`. +* If it has not already transmitted its own + `commitment_signed`: + - MUST send `commitment_signed`. + +On `channel_reestablish` after a reconnection: + +* If `next_funding_txid` matches the + factory-level change funding transaction: + - MUST retransmit `commitment_signed`. + +### The `factory_change_continue` Message + +Once the base node software have exchanged +`commitment_signed`, they indicate this to the +channel factory plugin (or equivalent). +The plugin MUST then arrange to make the new state +of the factory valid. +How this is done in unspecified; the expectation is +that the plugin MAY use `factory_piggyback` messages +to exchange the necessary cryptographic data to +make the new factory-level state valid. + +Once the plugin has made the new factory-level +state valid, and has reliably persisted this +information, it then indicates to the base node +software to exchange `factory_change_continue` (`12`) +messages. +The base node software then resume the channel once +they have both sent and received this message. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x000C` (`factory_change_continue`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types: + 1. type: 3072 (`factory_change_continue_tlv`) + 2. data: + * [`channel_id` : `channel_id`] + * [`sha256` : `funding_txid`] + * [`u16` : `funding_output_index`] + +Requirements: + +The sender: + +* MUST send this message as soon as its channel factory + plugin (or equivalent) indicates to do so. +* MUST include `factory_change_continue_tlv`. +* MUST set `funding_txid` and `funding_output_index` + to the same values it sent for + `factory_change_funding`. + +The receiver: + +* MUST check that the `factoy_change_continue_tlv` + exists. + - If not, MUST send a `warning` and close the + connection. +* MUST check that the `funding_txid` and + `funding_output_index` matches with its expected + values. + - If not, MUST send an `error` and fail the channel, + or send a `warning` and close the connection. +* If it has not yet sent `factory_change_continue`: + - MUST wait for its channel factory plugin (or + equivalent) to indicate to send the + `factory_change_continue` message, and send + that message. + +Nodes: + +* If they have sent and received this message: + - MUST resume the channel (i.e. remove it from + quiescence state), sending multiple + `commitment_signed` transactions with `batch` + TLVs, signing for the current funding transaction + and all factory-level change funding transactions. + - MUST wait for their plugin to indicate to send + `factory_change_locked` messages. +* On a restart, if they have not sent + `factory_change_continue` yet: + - MUST ask their plugin to indicate when to send + `factory_change_continue` messages. +* On a restart, if they have sent + `factory_change_continue`: + - MUST resend it. + +### The `factory_change_locked` Message + +After the factory change has been continued by the +nodes, the channel state itself is now valid for +both the current and new state of the factory. +At this point, the channel factory protocol should +now arrange to invalidate the current factory state, +so that only the new factory state will be depended +on. + +At this point, the channel factory protocol must +stabilize to a new state by invalidating the current +state and making the new state publishable (but not +yet confirmed) onchain. + +The channel factory protocol MAY also negotiate +another new factory state, by again triggering a +quiescence period and a `factory_change_init`. +This implies that *any*, but *at most one*, of the +possible new factory states could become the true +new state. +This parallels splicing, where multiple splice RBFs +might be done, and at most one splice transaction +can confirm and become the new funding transaction. + +Once the channel factory has stabilized to a new +state, the channel factory plugins (or equivalent) +indicate to their respective node software to exchange +`factory_change_locked` (`14`) messages. + +1. type: 32800 (`factory_message_id`) +2. data: + * [`u16` : `0x000E` (`factory_change_locked`)] +3. `tlv_stream` : `factory_message_tlvs` +4. types: + 1. type: 3584 (`factory_change_locked_tlv`) + 2. data: + * [`channel_id` : `channel_id`] + * [`sha256` : `locked_funding_txid`] + +Requirements: + +The sender: + +* MUST send this message as soon as its channel factory + plugin (or equivalent) indicates to do so. +* MUST include `factory_change_locked_tlv`. +* MUST set `locked_funding_txid` to a pending + new factory change funding transaction ID. + - MUST NOT set `locked_funding_txid` to the previous + funding transaction of the channel. + +The receiver: + +* MUST check that the `factory_change_locked_tlv` + exists. + - If not, MUST send a `warning` and close the + connection. +* MUST check that the given `locked_funding_txid` + are equal to what its own channel factory plugin + indicated or will indicate. + - If not, MUST send `warning` and close the + connection, or send `error` and fail the channel. + +Once a node has both sent and received +`factory_change_locked`: + +- MUST consider the indivated `locked_funding_txid` + as the new funding transaction for all future + `commitment_signed` and factory change negotiations. +- SHOULD discard the previous funding transaction and + alternative factory changes. + +On reconnection, a node: + +- MUST retransmit its last `factory_change_locked` + if the `commitment_number` is the same as before + sending `factory_change_locked`.