The peer channel protocol has three phases: establishment, normal operation, and closing.
- Channel
- Definition of
channel_id - Interactive Transaction Construction
- Channel Establishment v1
- Channel Establishment v2
- Channel Quiescence
- Channel Splicing
- Channel Close
- Normal Operation
- Forwarding HTLCs
cltv_expiry_deltaSelection- Adding an HTLC:
update_add_htlc - Removing an HTLC:
update_fulfill_htlc,update_fail_htlc, andupdate_fail_malformed_htlc - Batching channel messages
- Committing Updates So Far:
commitment_signed - Completing the Transition to the Updated State:
revoke_and_ack - Updating Fees:
update_fee
- Message Retransmission:
channel_reestablishmessage
- Definition of
- Authors
Some messages use a channel_id to identify the channel. It's
derived from the funding transaction by combining the funding_txid
and the funding_output_index, using big-endian exclusive-OR
(i.e. funding_output_index alters the last 2 bytes).
Prior to channel establishment, a temporary_channel_id is used,
which is a random nonce.
Note that as duplicate temporary_channel_ids may exist from different
peers, APIs which reference channels by their channel id before the funding
transaction is created are inherently unsafe. The only protocol-provided
identifier for a channel before funding_created has been exchanged is the
(source_node_id, destination_node_id, temporary_channel_id) tuple. Note that
any such APIs which reference channels by their channel id before the funding
transaction is confirmed are also not persistent - until you know the script
pubkey corresponding to the funding output nothing prevents duplicative channel
ids.
For channels established using the v2 protocol, the channel_id is the
SHA256(lesser-revocation-basepoint || greater-revocation-basepoint),
where the lesser and greater is based off the order of the basepoint.
When sending open_channel2, the peer's revocation basepoint is unknown.
A temporary_channel_id must be computed by using a zeroed out basepoint
for the non-initiator.
When sending accept_channel2, the temporary_channel_id from open_channel2
must be used, to allow the initiator to match the response to its request.
The revocation basepoints must be remembered by both peers for correct
operation anyway. They're known after the first exchange of messages,
obviating the need for a temporary_channel_id in subsequent messages.
By mixing information from both sides, they avoid channel_id collisions,
and they remove the dependency on the funding txid.
Interactive transaction construction allows two peers to collaboratively build a transaction for broadcast. This protocol is the foundation for dual-funded channels establishment (v2).
There are two parties to a transaction construction: an initiator
and a non-initiator.
The initiator is the peer which initiates the protocol, e.g.
for channel establishment v2 the initiator would be the peer which
sends open_channel2.
The protocol makes the following assumptions:
- The
feeratefor the transaction is known. - The
dust_limitfor the transaction is known. - The
nLocktimefor the transaction is known. - The
nVersionfor the transaction is known.
The initiator is responsible for paying the fees for the following fields,
to be referred to as the common fields.
- version
- segwit marker + flag
- input count
- output count
- locktime
The rest of the transaction bytes' fees are the responsibility of
the peer who contributed that input or output via tx_add_input or
tx_add_output, at the agreed upon feerate.
The initiator initiates the interactive transaction construction
protocol with tx_add_input. The non-initiator responds with any
of tx_add_input, tx_add_output, tx_remove_input, tx_remove_output, or
tx_complete. The protocol continues with the synchronous exchange
of interactive transaction protocol messages until both nodes have sent
and received a consecutive tx_complete. This is a turn-based protocol.
Once peers have exchanged consecutive tx_completes, the
interactive transaction construction protocol is considered concluded.
Both peers should construct the transaction and fail the negotiation
if an error is discovered.
This protocol is expressly designed to allow for parallel, multi-party
sessions to collectively construct a single transaction. This preserves
the ability to open multiple channels in a single transaction. While
serial_ids are generally chosen randomly, to maintain consistent transaction
ordering across all peer sessions, it is simplest to reuse received
serial_ids when forwarding them to other peers, inverting the bottom bit as
necessary to satisfy the parity requirement.
Here are a few example exchanges.
A, the initiator, has two inputs and an output (the funding output). B, the non-initiator has nothing to contribute.
+-------+ +-------+
| |--(1)- tx_add_input -->| |
| |<-(2)- tx_complete ----| |
| |--(3)- tx_add_input -->| |
| A |<-(4)- tx_complete ----| B |
| |--(5)- tx_add_output ->| |
| |<-(6)- tx_complete ----| |
| |--(7)- tx_complete --->| |
+-------+ +-------+
A, the initiator, contributes 2 inputs and an output that they then remove. B, the non-initiator, contributes 1 input and an output, but waits until A adds a second input before contributing.
Note that if A does not send a second input, the negotiation will end without B's contributions.
+-------+ +-------+
| |--(1)- tx_add_input ---->| |
| |<-(2)- tx_complete ------| |
| |--(3)- tx_add_output --->| |
| |<-(4)- tx_complete ------| |
| |--(5)- tx_add_input ---->| |
| A |<-(6)- tx_add_input -----| B |
| |--(7)- tx_remove_output >| |
| |<-(8)- tx_add_output ----| |
| |--(9)- tx_complete ----->| |
| |<-(10) tx_complete ------| |
+-------+ +-------+
This message contains a transaction input.
-
type: 66 (
tx_add_input) -
data:
- [
channel_id:channel_id] - [
u64:serial_id] - [
u16:prevtx_len] - [
prevtx_len*byte:prevtx] - [
u32:prevtx_vout] - [
u32:sequence] - [
tx_add_input_tlvs:tlvs]
- [
-
tlv_stream:tx_add_input_tlvs -
types:
- type: 0 (
shared_input_txid) - data:
- [
sha256:funding_txid]
- type: 0 (
The sending node:
- MUST add all sent inputs to the transaction
- MUST use a unique
serial_idfor each input currently added to the transaction - MUST set
sequenceto be less than or equal to 4294967293 (0xFFFFFFFD) - MUST NOT re-transmit inputs it has received from the peer
- if is the initiator:
- MUST send even
serial_ids
- MUST send even
- if is the non-initiator:
- MUST send odd
serial_ids
- MUST send odd
The receiving node:
- MUST add all received inputs to the transaction
- MUST fail the negotiation if:
sequenceis set to0xFFFFFFFEor0xFFFFFFFF- if
prevtx_lenis0:shared_input_txidis not setshared_input_txidandprevtx_voutdon't match the previous funding output- a previously added (and not removed) input already exists with
shared_input_txidset
- if
prevtx_lenis not0:prevtxandprevtx_voutare identical to a previously added (and not removed) inputprevtxis not a valid transactionprevtx_voutis greater or equal to the number of outputs onprevtx- the
scriptPubKeyof theprevtx_voutoutput ofprevtxis not exactly a 1-byte push opcode (for the numeric values0to16) followed by a data push between 2 and 40 bytes
- the
serial_idis already included in the transaction - the
serial_idhas the wrong parity - if has received 4096
tx_add_inputmessages during this negotiation
Each node must know the set of the transaction inputs. The non-initiator MAY omit this message.
serial_id is a randomly chosen number which uniquely identifies this input.
Inputs in the constructed transaction MUST be sorted by serial_id.
prevtx is the serialized transaction that contains the output this input
spends, used to verify that the input is non-malleable. It can be ommitted
(prevtx_len set to 0) when both peers already know that the input is
non-malleable (e.g. when it is the previous funding output).
prevtx_vout is the index of the output being spent.
sequence is the sequence number of this input: it must signal
replaceability, and the same value should be used across implementations
to avoid on-chain fingerprinting.
When sending tx_add_input, senders have no guarantee that the remote node
will complete the protocol in a timely manner. Malicious remote nodes could
delay messages or stop responding, which can result in a partially created
transaction that cannot be broadcast by the honest node. If the honest node
is locking the corresponding UTXO exclusively for this remote node, this can
be exploited to lock up the honest node's liquidity.
It is thus recommended that implementations keep UTXOs unlocked and actively reuse them in concurrent sessions, which guarantees that transactions created with honest nodes double-spend pending transactions with malicious nodes at no additional cost for the honest node.
Unfortunately, this will also create conflicts between concurrent sessions with honest nodes. This is a reasonable trade-off though because:
- on-chain funding attempts are relatively infrequent operations
- honest nodes should complete the protocol quickly, reducing the risk of conflicts
- failed attempts can simply be retried at no cost
This message adds a transaction output.
- type: 67 (
tx_add_output) - data:
- [
channel_id:channel_id] - [
u64:serial_id] - [
u64:sats] - [
u16:scriptlen] - [
scriptlen*byte:script]
- [
Either node:
- MAY omit this message
The sending node:
- MUST add all sent outputs to the transaction
- if is the initiator:
- MUST send even
serial_ids
- MUST send even
- if is the non-initiator:
- MUST send odd
serial_ids
- MUST send odd
The receiving node:
- MUST add all received outputs to the transaction
- MUST accept P2WSH, P2WPKH, P2TR
scripts - MAY fail the negotiation if
scriptis non-standard - MUST fail the negotiation if:
- the
serial_idis already included in the transaction - the
serial_idhas the wrong parity - it has received 4096
tx_add_outputmessages during this negotiation - the
satsamount is less than thedust_limit - the
satsamount is greater than 2,100,000,000,000,000 (MAX_MONEY)
- the
Each node must know the set of the transaction outputs.
serial_id is a randomly chosen number which uniquely identifies this output.
Outputs in the constructed transaction MUST be sorted by serial_id.
sats is the satoshi value of the output.
script is the scriptPubKey for the output (with its length omitted).
scripts are not required to follow standardness rules: non-standard
scripts such as OP_RETURN may be accepted, but the corresponding
transaction may fail to relay across the network.
This message removes an input from the transaction.
- type: 68 (
tx_remove_input) - data:
- [
channel_id:channel_id] - [
u64:serial_id]
- [
This message removes an output from the transaction.
- type: 69 (
tx_remove_output) - data:
- [
channel_id:channel_id] - [
u64:serial_id]
- [
The sending node:
- MUST NOT send a
tx_removewith aserial_idit did not add to the transaction or has already been removed
The receiving node:
- MUST remove the indicated input or output from the transaction
- MUST fail the negotiation if:
- the input or output identified by the
serial_idwas not added by the sender - the
serial_iddoes not correspond to a currently added input (or output)
- the input or output identified by the
This message signals the conclusion of a peer's transaction contributions.
- type: 70 (
tx_complete) - data:
- [
channel_id:channel_id]
- [
The nodes:
- MUST send this message in succession to conclude this protocol
The receiving node:
- MUST use the negotiated inputs and outputs to construct a transaction
- MUST fail the negotiation if:
- the peer's total input satoshis is less than their outputs. One MUST account for the peer's portion of the funding output when verifying compliance with this requirement.
- the peer's paid feerate does not meet or exceed the agreed
feerate(based on theminimum fee). - if is the non-initiator:
- the initiator's fees do not cover the
commonfields
- the initiator's fees do not cover the
- there are more than 252 inputs
- there are more than 252 outputs
- the estimated weight of the tx is greater than 400,000 (
MAX_STANDARD_TX_WEIGHT)
To signal the conclusion of exchange of transaction inputs and outputs.
Upon successful exchange of tx_complete messages, both nodes
should construct the transaction and proceed to the next portion of the
protocol. For channel establishment v2, exchanging commitment transactions.
For the minimum fee calculation see BOLT #3.
The maximum inputs and outputs are capped at 252. This effectively fixes the byte size of the input and output counts on the transaction to one (1).
-
type: 71 (
tx_signatures) -
data:
- [
channel_id:channel_id] - [
sha256:txid] - [
u16:num_witnesses] - [
num_witnesses*witness:witnesses] - [
tx_signatures_tlvs:tlvs]
- [
-
subtype:
witness -
data:
- [
u16:len] - [
len*byte:witness_data]
- [
-
tlv_stream:tx_signatures_tlvs -
types:
- type: 0 (
shared_input_signature) - data:
- [
signature:signature]
- type: 0 (
The sending node:
- if it has the lowest total satoshis contributed, as defined by total
tx_add_inputvalues, or both peers have contributed equal amounts but it has the lowestnode_id(sorted lexicographically):- MUST transmit their
tx_signaturesfirst
- MUST transmit their
- MUST order the
witnessesby theserial_idof the input they correspond to num_witnessess MUST equal the number of inputs they added- MUST use the
SIGHASH_ALL(0x01) flag on each signature
The receiving node:
- MUST fail the negotiation if:
- the message contains an empty
witness - the number of
witnessesdoes not equal the number of inputs added by the sending node - the
txiddoes not match the txid of the transaction - the
witnessesare non-standard - a signature uses a flag that is not
SIGHASH_ALL(0x01)
- the message contains an empty
- SHOULD apply the
witnessesto the transaction and broadcast it - MUST reply with their
tx_signaturesif not already transmitted
A strict ordering is used to decide which peer sends tx_signatures first.
This prevents deadlocks where each peer is waiting for the other peer to
send tx_signatures, and enables multiparty tx collaboration.
The witness_data is encoded as per bitcoin's wire protocol (a CompactSize number
of elements, with each element a CompactSize length and that many bytes following).
While the minimum fee is calculated and verified at tx_complete conclusion,
it is possible for the fee for the exchanged witness data to be underpaid.
It is the responsibility of the sending peer to correctly account for the
required fee.
This message initiates a replacement of the transaction after it's been completed.
-
type: 72 (
tx_init_rbf) -
data:
- [
channel_id:channel_id] - [
u32:locktime] - [
u32:feerate] - [
tx_init_rbf_tlvs:tlvs]
- [
-
tlv_stream:tx_init_rbf_tlvs -
types:
- type: 0 (
funding_output_contribution) - data:
- [
s64:satoshis]
- [
- type: 2 (
require_confirmed_inputs)
- type: 0 (
The sender:
- MUST set
feerategreater than or equal to 25/24 times thefeerateof the previously constructed transaction, rounded down. - If it contributes to the transaction's funding output:
- MUST set
funding_output_contribution
- MUST set
- If it requires the receiving node to only use confirmed inputs:
- MUST set
require_confirmed_inputs
- MUST set
- If it contributed to previous transactions:
- MUST ensure that the new transaction double-spends all other attempts,
by sending
tx_add_inputwith at least one input from each previous transaction construction attempt.
- MUST ensure that the new transaction double-spends all other attempts,
by sending
The recipient:
- MUST respond either with
tx_abortor withtx_ack_rbf - MUST respond with
tx_abortif:- the
feerateis not greater than or equal to 25/24 timesfeerateof the last successfully constructed transaction
- the
- MAY send
tx_abortfor any reason - MUST fail the negotiation if:
require_confirmed_inputsis set but it cannot provide confirmed inputs
feerate is the feerate this transaction will pay. It must be at least
1/24 greater than the last used feerate, rounded down to the nearest
satoshi to ensure there is progress.
E.g. if the last feerate was 520, the next sent feerate must be 541
(520 * 25 / 24 = 541.667, rounded down to 541).
If the previous transaction confirms in the middle of an RBF attempt, the attempt MUST be abandoned.
funding_output_contribution is the amount of satoshis that this peer
will contribute to the funding output of the transaction, when there is
such an output. Note that it may be different from the contribution
made in the previously completed transaction. If omitted, the sender is
not contributing to the funding output.
-
type: 73 (
tx_ack_rbf) -
data:
- [
channel_id:channel_id] - [
tx_ack_rbf_tlvs:tlvs]
- [
-
tlv_stream:tx_ack_rbf_tlvs -
types:
- type: 0 (
funding_output_contribution) - data:
- [
s64:satoshis]
- [
- type: 2 (
require_confirmed_inputs)
- type: 0 (
The sender:
- If it contributes to the transaction's funding output:
- MUST set
funding_output_contribution
- MUST set
- If it requires the receiving node to only use confirmed inputs:
- MUST set
require_confirmed_inputs
- MUST set
- If it contributed to previous transactions:
- MUST ensure that the new transaction double-spends all other attempts,
by sending
tx_add_inputwith at least one input from each previous transaction construction attempt.
- MUST ensure that the new transaction double-spends all other attempts,
by sending
The recipient:
- MUST respond with
tx_abortor with atx_add_inputmessage, restarting the interactive tx collaboration protocol. - MUST fail the negotiation if:
require_confirmed_inputsis set but it cannot provide confirmed inputs
funding_output_contribution is the amount of satoshis that this peer
will contribute to the funding output of the transaction, when there is
such an output. Note that it may be different from the contribution
made in the previously completed transaction. If omitted, the sender is
not contributing to the funding output.
It's recommended that a peer, rather than fail the RBF negotiation due to a large feerate change, instead stop contributing to the funding output, and decline to participate further in the transaction (by not contributing, they may obtain incoming liquidity at no cost).
- type: 74 (
tx_abort) - data:
- [
channel_id:channel_id] - [
u16:len] - [
len*byte:data]
- [
A sending node:
- MUST NOT have already transmitted
tx_signatures - SHOULD forget the current negotiation and reset their state.
- MAY send an empty
datafield. - when failure was caused by an invalid signature check:
- SHOULD include the raw, hex-encoded transaction in reply to a
tx_signaturesorcommitment_signedmessage.
- SHOULD include the raw, hex-encoded transaction in reply to a
A receiving node:
- if they have already sent
tx_signaturesto the peer:- MUST NOT forget the channel until any inputs to the negotiated tx have been spent.
- if they have not sent
tx_signatures:- SHOULD forget the current negotiation and reset their state.
- if they have not sent
tx_abort:- MUST echo back
tx_abort
- MUST echo back
- if
datais not composed solely of printable ASCII characters (For reference: the printable character set includes byte values 32 through 126, inclusive):- SHOULD NOT print out
dataverbatim.
- SHOULD NOT print out
A receiving node, if they've already sent their tx_signatures has no guarantee
that the transaction won't be signed and published by their peer. They must remember
the transaction and channel (if appropriate) until the transaction is no longer
eligible to be spent (i.e. any input has been spent in a different transaction).
The tx_abort message allows for the cancellation of an in progress negotiation,
and a return to the initial starting state. It is distinct from the error
message, which triggers a channel close.
Echoing back tx_abort allows the peer to ack that they've seen the abort message,
permitting the originating peer to terminate the in-flight process without
worrying about stale messages.
After authenticating and initializing a connection (BOLT #8 and BOLT #1, respectively), channel establishment may begin.
There are two pathways for establishing a channel, a legacy version presented here,
and a second version (below). Which channel
establishment protocols are available for use is negotiated in the init message.
This consists of the funding node (funder) sending an open_channel message,
followed by the responding node (fundee) sending accept_channel. With the
channel parameters locked in, the funder is able to create the funding
transaction and both versions of the commitment transaction, as described in
BOLT #3.
The funder then sends the outpoint of the funding output with the funding_created
message, along with the signature for the fundee's version of the commitment
transaction. Once the fundee learns the funding outpoint, it's able to
generate the signature for the funder's version of the commitment transaction and send it
over using the funding_signed message.
Once the channel funder receives the funding_signed message, it
must broadcast the funding transaction to the Bitcoin network. After
the funding_signed message is sent/received, both sides should wait
for the funding transaction to enter the blockchain and reach the
specified depth (number of confirmations). After both sides have sent
the channel_ready message, the channel is established and can begin
normal operation. The channel_ready message includes information
that will be used to construct channel authentication proofs.
+-------+ +-------+
| |--(1)--- open_channel ----->| |
| |<-(2)-- accept_channel -----| |
| | | |
| A |--(3)-- funding_created --->| B |
| |<-(4)-- funding_signed -----| |
| | | |
| |--(5)--- channel_ready ---->| |
| |<-(6)--- channel_ready -----| |
+-------+ +-------+
- where node A is 'funder' and node B is 'fundee'
If this fails at any stage, or if one node decides the channel terms offered by the other node are not suitable, the channel establishment fails.
Note that multiple channels can operate in parallel, as all channel
messages are identified by either a temporary_channel_id (before the
funding transaction is created) or a channel_id (derived from the
funding transaction).
This message contains information about a node and indicates its desire to set up a new channel. This is the first step toward creating the funding transaction and both versions of the commitment transaction.
-
type: 32 (
open_channel) -
data:
- [
chain_hash:chain_hash] - [
32*byte:temporary_channel_id] - [
u64:funding_satoshis] - [
u64:push_msat] - [
u64:dust_limit_satoshis] - [
u64:max_htlc_value_in_flight_msat] - [
u64:channel_reserve_satoshis] - [
u64:htlc_minimum_msat] - [
u32:feerate_per_kw] - [
u16:to_self_delay] - [
u16:max_accepted_htlcs] - [
point:funding_pubkey] - [
point:revocation_basepoint] - [
point:payment_basepoint] - [
point:delayed_payment_basepoint] - [
point:htlc_basepoint] - [
point:first_per_commitment_point] - [
byte:channel_flags] - [
open_channel_tlvs:tlvs]
- [
-
tlv_stream:open_channel_tlvs -
types:
- type: 0 (
upfront_shutdown_script) - data:
- [
...*byte:shutdown_scriptpubkey]
- [
- type: 1 (
channel_type) - data:
- [
...*byte:type]
- [
- type: 0 (
The chain_hash value denotes the exact blockchain that the opened channel will
reside within. This is usually the genesis hash of the respective blockchain.
The existence of the chain_hash allows nodes to open channels
across many distinct blockchains as well as have channels within multiple
blockchains opened to the same peer (if it supports the target chains).
The temporary_channel_id is used to identify this channel on a per-peer basis until the
funding transaction is established, at which point it is replaced
by the channel_id, which is derived from the funding transaction.
funding_satoshis is the amount the sender is putting into the
channel. push_msat is an amount of initial funds that the sender is
unconditionally giving to the receiver. dust_limit_satoshis is the
threshold below which outputs should not be generated for this node's
commitment or HTLC transactions (i.e. HTLCs below this amount plus
HTLC transaction fees are not enforceable on-chain). This reflects the
reality that tiny outputs are not considered standard transactions and
will not propagate through the Bitcoin network. channel_reserve_satoshis
is the minimum amount that the other node is to keep as a direct
payment. htlc_minimum_msat indicates the smallest value HTLC this
node will accept.
max_htlc_value_in_flight_msat is a cap on total value of outstanding
HTLCs offered by the remote node, which allows the local node to limit its
exposure to HTLCs; similarly, max_accepted_htlcs limits the number of
outstanding HTLCs the remote node can offer.
feerate_per_kw indicates the initial fee rate in satoshi per 1000-weight
(i.e. 1/4 the more normally-used 'satoshi per 1000 vbytes') that this
side will pay for commitment and HTLC transactions, as described in
BOLT #3 (this can be adjusted
later with an update_fee message).
to_self_delay is the number of blocks that the other node's to-self
outputs must be delayed, using OP_CHECKSEQUENCEVERIFY delays; this
is how long it will have to wait in case of breakdown before redeeming
its own funds.
funding_pubkey is the public key in the 2-of-2 multisig script of
the funding transaction output.
The various _basepoint fields are used to derive unique
keys as described in BOLT #3 for each commitment
transaction. Varying these keys ensures that the transaction ID of
each commitment transaction is unpredictable to an external observer,
even if one commitment transaction is seen; this property is very
useful for preserving privacy when outsourcing penalty transactions to
third parties.
first_per_commitment_point is the per-commitment point to be used
for the first commitment transaction,
Only the least-significant bit of channel_flags is currently
defined: announce_channel. This indicates whether the initiator of
the funding flow wishes to advertise this channel publicly to the
network, as detailed within BOLT #7.
The shutdown_scriptpubkey allows the sending node to commit to where
funds will go on mutual close, which the remote node should enforce
even if a node is compromised later.
The option_support_large_channel is a feature used to let everyone
know this node will accept funding_satoshis greater than or equal to 2^24.
Since it's broadcast in the node_announcement message other nodes can use it to identify peers
willing to accept large channel even before exchanging the init message with them.
Channel types are an explicit enumeration: for convenience of future definitions they reuse even feature bits, but they are not an arbitrary combination (they represent the persistent features which affect the channel operation).
The currently defined basic types are:
option_static_remotekey(bit 12)option_anchorsandoption_static_remotekey(bits 22 and 12)
Each basic type has the following variations allowed:
option_scid_alias(bit 46)option_zeroconf(bit 50)
The sending node:
- MUST ensure the
chain_hashvalue identifies the chain it wishes to open the channel within. - MUST ensure
temporary_channel_idis unique from any other channel ID with the same peer. - if both nodes advertised
option_support_large_channel:- MAY set
funding_satoshisgreater than or equal to 2^24 satoshi.
- MAY set
- otherwise:
- MUST set
funding_satoshisto less than 2^24 satoshi.
- MUST set
- MUST set
push_msatto equal or less than 1000 *funding_satoshis. - MUST set
funding_pubkey,revocation_basepoint,htlc_basepoint,payment_basepoint, anddelayed_payment_basepointto valid secp256k1 pubkeys in compressed format. - MUST set
first_per_commitment_pointto the per-commitment point to be used for the initial commitment transaction, derived as specified in BOLT #3. - MUST set
channel_reserve_satoshisgreater than or equal todust_limit_satoshis. - MUST set undefined bits in
channel_flagsto 0. - if both nodes advertised the
option_upfront_shutdown_scriptfeature:- MUST include
upfront_shutdown_scriptwith either a validshutdown_scriptpubkeyas required byshutdownscriptpubkey, or a zero-lengthshutdown_scriptpubkey(ie.0x0000).
- MUST include
- otherwise:
- MAY include
upfront_shutdown_script.
- MAY include
- if it includes
open_channel_tlvs:- MUST include
upfront_shutdown_script. - MUST set
channel_type:- MUST set it to a defined type representing the type it wants.
- MUST use the smallest bitmap possible to represent the channel type.
- SHOULD NOT set it to a type containing a feature which was not negotiated.
- if
announce_channelistrue(not0):- MUST NOT send
channel_typewith theoption_scid_aliasbit set.
- MUST NOT send
- MUST include
The sending node SHOULD:
- set
to_self_delaysufficient to ensure the sender can irreversibly spend a commitment transaction output, in case of misbehavior by the receiver. - set
feerate_per_kwto at least the rate it estimates would cause the transaction to be immediately included in a block. - set
dust_limit_satoshisto a sufficient value to allow commitment transactions to propagate through the Bitcoin network. - set
dust_limit_satoshisto a sufficient value to allow HTLC transactions to propagate through the Bitcoin network. - set
htlc_minimum_msatto the minimum value HTLC it's willing to accept from this peer.
The receiving node MUST:
- ignore undefined bits in
channel_flags. - if the message doesn't include a
channel_type:- fail the channel.
- if the connection has been re-established after receiving a previous
open_channel, BUT before receiving afunding_createdmessage:- accept a new
open_channelmessage. - discard the previous
open_channelmessage.
- accept a new
- if
option_dual_fundhas been negotiated:- fail the channel.
The receiving node MAY fail the channel if:
announce_channelisfalse(0), yet it wishes to publicly announce the channel.funding_satoshisis too small.- it considers
htlc_minimum_msattoo large. - it considers
max_htlc_value_in_flight_msattoo small. - it considers
channel_reserve_satoshistoo large. - it considers
max_accepted_htlcstoo small. - it considers
dust_limit_satoshistoo large (see BOLT 3).
The receiving node MUST fail the channel if:
- the
chain_hashvalue is set to a hash of a chain that is unknown to the receiver. push_msatis greater thanfunding_satoshis* 1000.to_self_delayis unreasonably large.max_accepted_htlcsis greater than 483.- it considers
feerate_per_kwtoo small for timely processing or unreasonably large. funding_pubkey,revocation_basepoint,htlc_basepoint,payment_basepoint, ordelayed_payment_basepointare not valid secp256k1 pubkeys in compressed format.dust_limit_satoshisis greater thanchannel_reserve_satoshis.dust_limit_satoshisis smaller than354 satoshis(see BOLT 3).- the funder's amount for the initial commitment transaction is not sufficient for full fee payment.
- both
to_localandto_remoteamounts for the initial commitment transaction are less than or equal tochannel_reserve_satoshis(see BOLT 3). funding_satoshisis greater than or equal to 2^24 and the receiver does not supportoption_support_large_channel.- the
channel_typeis not suitable. - the
channel_typeincludesoption_zeroconfand it does not trust the sender to open an unconfirmed channel.
The receiving node MUST NOT:
- consider funds received, using
push_msat, to be received until the funding transaction has reached sufficient depth.
The requirement for funding_satoshis to be less than 2^24 satoshi was a temporary self-imposed limit while implementations were not yet considered stable, it can be lifted by advertising option_support_large_channel.
The channel reserve is specified by the peer's channel_reserve_satoshis: 1% of the channel total is suggested. Each side of a channel maintains this reserve so it always has something to lose if it were to try to broadcast an old, revoked commitment transaction. Initially, this reserve may not be met, as only one side has funds; but the protocol ensures that there is always progress toward meeting this reserve, and once met, it is maintained.
The sender can unconditionally give initial funds to the receiver using a non-zero push_msat, but even in this case we ensure that the funder has sufficient remaining funds to pay fees and that one side has some amount it can spend (which also implies there is at least one non-dust output). Note that, like any other on-chain transaction, this payment is not certain until the funding transaction has been confirmed sufficiently (with a danger of double-spend until this occurs) and may require a separate method to prove payment via on-chain confirmation.
The feerate_per_kw is generally only of concern to the sender (who pays the fees), but there is also the fee rate paid by HTLC transactions; thus, unreasonably large fee rates can also penalize the recipient.
Separating the htlc_basepoint from the payment_basepoint improves security: a node needs the secret associated with the htlc_basepoint to produce HTLC signatures for the protocol, but the secret for the payment_basepoint can be in cold storage.
The requirement that channel_reserve_satoshis is not considered dust
according to dust_limit_satoshis eliminates cases where all outputs
would be eliminated as dust. The similar requirements in
accept_channel ensure that both sides' channel_reserve_satoshis
are above both dust_limit_satoshis.
The receiver should not accept large dust_limit_satoshis, as this could be
used in griefing attacks, where the peer publishes its commitment with a lot
of dust htlcs, which effectively become miner fees. But it must allow values
higher than the standard Bitcoin Core dust limits, since HTLC outputs need to
be spent by a second-stage transaction at a feerate matching the current
on-chain feerate.
Details for how to handle a channel failure can be found in BOLT 5:Failing a Channel.
This message contains information about a node and indicates its acceptance of the new channel. This is the second step toward creating the funding transaction and both versions of the commitment transaction.
-
type: 33 (
accept_channel) -
data:
- [
32*byte:temporary_channel_id] - [
u64:dust_limit_satoshis] - [
u64:max_htlc_value_in_flight_msat] - [
u64:channel_reserve_satoshis] - [
u64:htlc_minimum_msat] - [
u32:minimum_depth] - [
u16:to_self_delay] - [
u16:max_accepted_htlcs] - [
point:funding_pubkey] - [
point:revocation_basepoint] - [
point:payment_basepoint] - [
point:delayed_payment_basepoint] - [
point:htlc_basepoint] - [
point:first_per_commitment_point] - [
accept_channel_tlvs:tlvs]
- [
-
tlv_stream:accept_channel_tlvs -
types:
- type: 0 (
upfront_shutdown_script) - data:
- [
...*byte:shutdown_scriptpubkey]
- [
- type: 1 (
channel_type) - data:
- [
...*byte:type]
- [
- type: 0 (
The temporary_channel_id MUST be the same as the temporary_channel_id in
the open_channel message.
The sender:
- if
channel_typeincludesoption_zeroconf:- MUST set
minimum_depthto zero.
- MUST set
- otherwise:
- SHOULD set
minimum_depthto a number of blocks it considers reasonable to avoid double-spending of the funding transaction.
- SHOULD set
- MUST set
channel_reserve_satoshisgreater than or equal todust_limit_satoshisfrom theopen_channelmessage. - MUST set
dust_limit_satoshisless than or equal tochannel_reserve_satoshisfrom theopen_channelmessage. - MUST set
channel_typeto thechannel_typefromopen_channel.
The receiver:
- if
minimum_depthis unreasonably large:- MAY fail the channel.
- if
channel_reserve_satoshisis less thandust_limit_satoshiswithin theopen_channelmessage:- MUST fail the channel.
- if
channel_reserve_satoshisfrom theopen_channelmessage is less thandust_limit_satoshis:- MUST fail the channel.
- if the message doesn't include a
channel_type:- MUST fail the channel.
- if
channel_typedoes not match thechannel_typefromopen_channel:- MUST fail the channel.
Other fields have the same requirements as their counterparts in open_channel.
This message describes the outpoint which the funder has created for
the initial commitment transactions. After receiving the peer's
signature, via funding_signed, it will broadcast the funding transaction.
- type: 34 (
funding_created) - data:
- [
32*byte:temporary_channel_id] - [
sha256:funding_txid] - [
u16:funding_output_index] - [
signature:signature]
- [
The sender MUST set:
temporary_channel_idthe same as thetemporary_channel_idin theopen_channelmessage.funding_txidto the transaction ID of a non-malleable transaction,- and MUST NOT broadcast this transaction.
funding_output_indexto the output number of that transaction that corresponds the funding transaction output, as defined in BOLT #3.signatureto the valid signature using itsfunding_pubkeyfor the initial commitment transaction, as defined in BOLT #3.
The sender:
- when creating the funding transaction:
- SHOULD use only BIP141 (Segregated Witness) inputs.
- SHOULD ensure the funding transaction confirms in the next 2016 blocks.
The recipient:
- if
signatureis incorrect OR non-compliant with LOW-S-standard ruleLOWS:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
The funding_output_index can only be 2 bytes, since that's how it's packed into the channel_id and used throughout the gossip protocol. The limit of 65535 outputs should not be overly burdensome.
A transaction with all Segregated Witness inputs is not malleable, hence the funding transaction recommendation.
The funder may use CPFP on a change output to ensure that the funding transaction confirms before 2016 blocks, otherwise the fundee may forget that channel.
This message gives the funder the signature it needs for the first commitment transaction, so it can broadcast the transaction knowing that funds can be redeemed, if need be.
This message introduces the channel_id to identify the channel. It's derived from the funding transaction by combining the funding_txid and the funding_output_index, using big-endian exclusive-OR (i.e. funding_output_index alters the last 2 bytes).
- type: 35 (
funding_signed) - data:
- [
channel_id:channel_id] - [
signature:signature]
- [
Both peers:
- MUST use the negotiated
channel_typefor all commitment transactions.
The sender MUST set:
channel_idby exclusive-OR of thefunding_txidand thefunding_output_indexfrom thefunding_createdmessage.signatureto the valid signature, using itsfunding_pubkeyfor the initial commitment transaction, as defined in BOLT #3.
The recipient:
- if
signatureis incorrect OR non-compliant with LOW-S-standard ruleLOWS:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- MUST NOT broadcast the funding transaction before receipt of a valid
funding_signed. - on receipt of a valid
funding_signed:- SHOULD broadcast the funding transaction.
We generate the commitment transaction at this point, using the channel_type
that was communicated in the open_channel and accept_channel messages.
This channel_type determines the channel commitment format for the total
lifetime of the channel.
This message (which used to be called funding_locked) indicates that the funding transaction has sufficient confirms for channel use. Once both nodes have sent this, the channel enters normal operating mode.
Note that the opener is free to send this message at any time (since it presumably trusts itself), but the
accepter would usually wait until the funding has reached the minimum_depth asked for in accept_channel.
-
type: 36 (
channel_ready) -
data:
- [
channel_id:channel_id] - [
point:second_per_commitment_point] - [
channel_ready_tlvs:tlvs]
- [
-
tlv_stream:channel_ready_tlvs -
types:
- type: 1 (
short_channel_id) - data:
- [
short_channel_id:alias]
- [
- type: 1 (
The sender:
- MUST NOT send
channel_readyunless outpoint of given byfunding_txidandfunding_output_indexin thefunding_createdmessage pays exactlyfunding_satoshisto the scriptpubkey specified in BOLT #3. - if it is not the node opening the channel:
- SHOULD wait until the funding transaction has reached
minimum_depthbefore sending this message.
- SHOULD wait until the funding transaction has reached
- MUST set
second_per_commitment_pointto the per-commitment point to be used for commitment transaction #1, derived as specified in BOLT #3. - if
option_scid_aliaswas negotiated:- MUST set
short_channel_idalias.
- MUST set
- otherwise:
- MAY set
short_channel_idalias.
- MAY set
- if it sets
alias:- if the
announce_channelbit was set inopen_channel:- SHOULD initially set
aliasto value not related to the realshort_channel_id.
- SHOULD initially set
- otherwise:
- MUST set
aliasto a value not related to the realshort_channel_id.
- MUST set
- MUST NOT send the same
aliasfor multiple peers or use an alias which collides with ashort_channel_idof a channel on the same node. - MUST always recognize the
aliasas ashort_channel_idfor incoming HTLCs to this channel. - if
channel_typehasoption_scid_aliasset:- MUST NOT allow incoming HTLCs to this channel using the real
short_channel_id
- MUST NOT allow incoming HTLCs to this channel using the real
- MAY send multiple
channel_readymessages to the same peer with differentaliasvalues.
- if the
- otherwise:
- MUST wait until the funding transaction has reached
minimum_depthbefore sending this message.
- MUST wait until the funding transaction has reached
The sender:
A non-funding node (fundee):
- SHOULD forget the channel if it does not see the correct funding transaction after a timeout of 2016 blocks.
The receiver:
- MAY use any of the
aliasit received, in BOLT 11rfields. - if
channel_typehasoption_scid_aliasset:- MUST NOT use the real
short_channel_idin BOLT 11rfields.
- MUST NOT use the real
From the point of waiting for channel_ready onward, either node MAY
send an error and fail the channel if it does not receive a required response from the
other node after a reasonable timeout.
The non-funder can simply forget the channel ever existed, since no
funds are at risk. If the fundee were to remember the channel forever, this
would create a Denial of Service risk; therefore, forgetting it is recommended
(even if the promise of push_msat is significant).
If the fundee forgets the channel before it was confirmed, the funder will need to broadcast the commitment transaction to get his funds back and open a new channel. To avoid this, the funder should ensure the funding transaction confirms in the next 2016 blocks.
The alias here is required for two distinct use cases. The first one is
for routing payments through channels that are not confirmed yet (since
the real short_channel_id is unknown until confirmation). The second one
is to provide one or more aliases to use for private channels (even once
a real short_channel_id is available).
While a node can send multiple alias, it must remember all of the
ones it has sent so it can use them should they be requested by
incoming HTLCs. The recipient only need remember one, for use in
r route hints in BOLT 11 invoices.
If an RBF negotiation is in progress when a channel_ready message is
exchanged, the negotiation must be abandoned.
This is a revision of the channel establishment protocol.
It changes the previous protocol to allow the accept_channel2 peer
(the accepter/non-initiator) to contribute inputs to the funding
transaction, via the interactive transaction construction protocol.
+-------+ +-------+
| |--(1)--- open_channel2 ----->| |
| |<-(2)--- accept_channel2 -----| |
| | | |
--->| | <tx collaboration> | |
| | | | |
| | |--(3)-- commitment_signed -->| |
| | |<-(4)-- commitment_signed ---| |
| | A | | B |
| | |<-(5)-- tx_signatures -------| |
| | |--(6)-- tx_signatures ------>| |
| | | | |
| | |--(a)--- tx_init_rbf -------->| |
----| |<-(b)--- tx_ack_rbf ----------| |
| | | |
| | <tx rbf collaboration> | |
| | | |
| |--(c)-- commitment_signed -->| |
| |<-(d)-- commitment_signed ---| |
| | | |
| |<-(e)-- tx_signatures -------| |
| |--(f)-- tx_signatures ------>| |
| | | |
| |--(7)--- channel_ready ----->| |
| |<-(8)--- channel_ready ------| |
+-------+ +-------+
- where node A is *opener*/*initiator* and node B is
*accepter*/*non-initiator*
This message initiates the v2 channel establishment workflow.
-
type: 64 (
open_channel2) -
data:
- [
chain_hash:chain_hash] - [
channel_id:temporary_channel_id] - [
u32:funding_feerate_perkw] - [
u32:commitment_feerate_perkw] - [
u64:funding_satoshis] - [
u64:dust_limit_satoshis] - [
u64:max_htlc_value_in_flight_msat] - [
u64:htlc_minimum_msat] - [
u16:to_self_delay] - [
u16:max_accepted_htlcs] - [
u32:locktime] - [
point:funding_pubkey] - [
point:revocation_basepoint] - [
point:payment_basepoint] - [
point:delayed_payment_basepoint] - [
point:htlc_basepoint] - [
point:first_per_commitment_point] - [
point:second_per_commitment_point] - [
byte:channel_flags] - [
opening_tlvs:tlvs]
- [
-
tlv_stream:opening_tlvs -
types:
- type: 0 (
upfront_shutdown_script) - data:
- [
...*byte:shutdown_scriptpubkey]
- [
- type: 1 (
channel_type) - data:
- [
...*byte:type]
- [
- type: 2 (
require_confirmed_inputs)
- type: 0 (
Rationale and Requirements are the same as for open_channel,
with the following additions.
If nodes have negotiated option_dual_fund:
- the opening node:
- MUST NOT send
open_channel
- MUST NOT send
The sending node:
- MUST set
channel_type - MUST set
funding_feerate_perkwto the feerate for this transaction - If it requires the receiving node to only use confirmed inputs:
- MUST set
require_confirmed_inputs
- MUST set
The receiving node:
- MAY fail the negotiation if:
- the
locktimeis unacceptable - the
funding_feerate_perkwis unacceptable
- the
- MUST fail the negotiation if:
require_confirmed_inputsis set but it cannot provide confirmed inputschannel_typeis not set
temporary_channel_id MUST be derived using a zeroed out basepoint for the
peer's revocation basepoint. This allows the peer to return channel-assignable
errors before the accepter's revocation basepoint is known.
funding_feerate_perkw indicates the fee rate that the opening node will
pay for the funding transaction in satoshi per 1000-weight, as described
in BOLT-3, Appendix F.
locktime is the locktime for the funding transaction.
The receiving node, if the locktime or funding_feerate_perkw is considered
out of an acceptable range, may fail the negotiation. However, it is
recommended that the accepter permits the channel open to proceed
without their participation in the channel's funding.
Note that open_channel's channel_reserve_satoshi has been omitted.
Instead, the channel reserve is fixed at 1% of the total channel balance
(open_channel2.funding_satoshis + accept_channel2.funding_satoshis)
rounded down to the nearest whole satoshi or the dust_limit_satoshis,
whichever is greater.
Note that push_msat has been omitted.
second_per_commitment_point is now sent here (as well as in channel_ready)
as a convenience for implementations.
The sending node may require the other participant to only use confirmed inputs. This ensures that the sending node doesn't end up paying the fees of a low feerate unconfirmed ancestor of one of the other participant's inputs.
This message contains information about a node and indicates its acceptance of the new channel.
-
type: 65 (
accept_channel2) -
data:
- [
channel_id:temporary_channel_id] - [
u64:funding_satoshis] - [
u64:dust_limit_satoshis] - [
u64:max_htlc_value_in_flight_msat] - [
u64:htlc_minimum_msat] - [
u32:minimum_depth] - [
u16:to_self_delay] - [
u16:max_accepted_htlcs] - [
point:funding_pubkey] - [
point:revocation_basepoint] - [
point:payment_basepoint] - [
point:delayed_payment_basepoint] - [
point:htlc_basepoint] - [
point:first_per_commitment_point] - [
point:second_per_commitment_point] - [
accept_tlvs:tlvs]
- [
-
tlv_stream:accept_tlvs -
types:
- type: 0 (
upfront_shutdown_script) - data:
- [
...*byte:shutdown_scriptpubkey]
- [
- type: 1 (
channel_type) - data:
- [
...*byte:type]
- [
- type: 2 (
require_confirmed_inputs)
- type: 0 (
Rationale and Requirements are the same as listed above,
for accept_channel with the following
additions.
The accepting node:
- MUST use the
temporary_channel_idof theopen_channel2message. - MUST set
channel_typeto thechannel_typefromopen_channel2. - MAY respond with a
funding_satoshisvalue of zero. - If it requires the opening node to only use confirmed inputs:
- MUST set
require_confirmed_inputs.
- MUST set
The receiving node:
- MUST fail the negotiation if:
require_confirmed_inputsis set but it cannot provide confirmed inputs.channel_typeis not set.
The funding_satoshis is the amount of bitcoin in satoshis
the accepter will be contributing to the channel's funding transaction.
Note that accept_channel's channel_reserve_satoshi has been omitted.
Instead, the channel reserve is fixed at 1% of the total channel balance
(open_channel2.funding_satoshis + accept_channel2.funding_satoshis)
rounded down to the nearest whole satoshi or the dust_limit_satoshis,
whichever is greater.
Funding composition for channel establishment v2 makes use of the Interactive Transaction Construction protocol, with the following additional caveats.
The sending node:
- if the receiver set
require_confirmed_inputsinopen_channel2,accept_channel2,tx_init_rbfortx_ack_rbf:- MUST NOT send a
tx_add_inputthat contains an unconfirmed input
- MUST NOT send a
The sending node:
- if is the opener:
- MUST send at least one
tx_add_output, which contains the channel's funding output
- MUST send at least one
The channel funding output must be added by the opener, who pays its fees.
Upon receipt of consecutive tx_completes, the receiving node:
- if is the accepter:
- MUST fail the negotiation if:
- no funding output was received
- the value of the funding output is not equal to the sum of
open_channel2.funding_satoshisandaccept_channel2.funding_satoshis - the value of the funding output is less than the
dust_limit
- MUST fail the negotiation if:
- if this is an RBF attempt:
- MUST fail the negotiation if:
- the transaction's total fees is less than the last successfully negotiated transaction's fees
- the transaction does not share at least one input with each previous funding transaction
- MUST fail the negotiation if:
- if it has sent
require_confirmed_inputsinopen_channel2,accept_channel2,tx_init_rbfortx_ack_rbf:- MUST fail the negotiation if:
- one of the inputs added by the other peer is unconfirmed
- MUST fail the negotiation if:
This message is exchanged by both peers. It contains the signatures for
the first commitment transaction, which uses a format determined by the
channel_type sent in open_channel2 and accept_channel2.
Rationale and Requirements are the same as listed below,
for commitment_signed with the following additions.
The sending node:
- MUST send zero HTLCs.
- MUST remember the details of this funding transaction.
The receiving node:
- if the message has one or more HTLCs:
- MUST fail the negotiation
- if it has not already transmitted its
commitment_signed:- MUST send
commitment_signed
- MUST send
- Otherwise:
- MUST send
tx_signaturesif it should sign first, as specified in thetx_signaturesrequirements
- MUST send
The first commitment transaction has no HTLCs.
Once peers are ready to exchange commitment signatures, they must remember the details of the funding transaction to allow resuming the signatures exchange if a disconnection happens.
After a valid commitment_signed has been received
from the peer and a commitment_signed has been sent, a peer:
- MUST transmit
tx_signatureswith their signatures for the funding transaction, following the order specified in thetx_signaturesrequirements
The sending node:
- MUST verify it has received a valid commitment signature from its peer
- MUST remember the details of this funding transaction
- if it has NOT received a valid
commitment_signedmessage:- MUST NOT send a
tx_signaturesmessage
- MUST NOT send a
The receiving node:
- if has already sent or received a
channel_readymessage for this channel:- MUST ignore this message
- if the
witnessweight lowers the effectivefeeratebelow the opener's feerate for the funding transaction and the effectivefeerateis determined by the receiving node to be insufficient for getting the transaction confirmed in a timely manner:- SHOULD broadcast their commitment transaction, closing the channel
- SHOULD double-spend their channel inputs when there is a productive opportunity to do so; effectively canceling this channel open
- SHOULD apply
witnessesto the funding transaction and broadcast it
A peer sends their tx_signatures after receiving a valid commitment_signed
message, following the order specified in the tx_signatures section.
In the case where a peer provides valid witness data that causes their paid
feerate to fall beneath the open_channel2.funding_feerate_perkw, the channel
should be considered failed and the channel should be double-spent when
there is a productive opportunity to do so. This should disincentivize
peers from underpaying fees.
After the funding transaction has been broadcast, it can be replaced by a transaction paying more fees to make the channel confirm faster.
The sender of tx_init_rbf:
- MAY be either the initiator or the accepter
- If the sender is the accepter, it becomes the initiator of the
interactive-txsession and thus:- MUST send
tx_add_outputfor the channel output - MUST pay the fees for the shared transaction fields
- MUST send
- If the sender is the accepter, it becomes the initiator of the
- MUST NOT have sent or received a
channel_readymessage.
The recipient:
- MUST fail the negotiation if they have already sent or received
channel_ready - MAY fail the negotiation for any reason
If a valid channel_ready message is received in the middle of an
RBF attempt, the attempt MUST be abandoned.
Peers can use different values in tx_init_rbf.funding_output_contribution
and tx_ack_rbf.funding_output_contribution from the amounts transmitted
in open_channel2 and accept_channel2: they are allowed to change how
much they wish to commit to the funding output.
It's recommended that a peer, rather than fail the RBF negotiation due to
a large feerate change, instead sets their sats to zero, and decline to
participate further in the channel funding: by not contributing, they
may obtain incoming liquidity at no cost.
We allow both nodes to initiate RBF, because any one of them may want to take this opportunity to contribute additional funds to the channel without waiting for the initial funding transaction to confirm.
Various fundamental changes, in particular protocol upgrades, are easiest on channels where both commitment transactions match, and no pending updates are in flight. We define a protocol to quiesce the channel by indicating that "SomeThing Fundamental is Underway".
- type: 2 (
stfu) - data:
- [
channel_id:channel_id] - [
u8:initiator]
- [
The sender of stfu:
- MUST NOT send
stfuunlessoption_quiesceis negotiated. - MUST NOT send
stfuif any of the sender's htlc additions, htlc removals or fee updates are pending for either peer. - MUST NOT send
stfutwice. - if it is replying to an
stfu:- MUST set
initiatorto 0
- MUST set
- otherwise:
- MUST set
initiatorto 1
- MUST set
- MUST set
channel_idto the id of the channel to quiesce. - MUST now consider the channel to be quiescing.
- MUST NOT send an update message after
stfu.
The receiver of stfu:
- if it has sent
stfuthen:- MUST now consider the channel to be quiescent
- otherwise:
- SHOULD NOT send any more update messages.
- MUST reply with
stfuonce it can do so.
Both nodes:
- MUST disconnect after 60 seconds of quiescence if the HTLCs are pending.
Upon disconnection:
- the channel is no longer considered quiescent.
Dependent Protocols:
- MUST specify all states that terminate quiescence.
- NOTE: this prevents batching executions of protocols that depend on quiescence.
The normal use would be to cease sending updates, then wait for all the current updates to be acknowledged by both peers, then start quiescence. For some protocols, choosing the initiator matters, so this flag is sent.
If both sides send stfu simultaneously, they will both set
initiator to 1, in which case the "initiator" is arbitrarily
considered to be the channel funder (the sender of open_channel).
The quiescence effect is exactly the same as if one had replied to the
other.
Dependent protocols have to specify termination conditions to prevent the need for disconnection to resume channel traffic. An explicit resume message was considered but rejected since it introduces a number of edge cases that make bilateral consensus of channel state significantly more complex to maintain. This introduces the derivative property that it is impossible to batch multiple downstream protocols in the same quiescence session.
Splicing is the term given for replacing the funding transaction with a new one. For simplicity, splicing takes place once a channel is quiescent.
Operation returns to normal once the splice transaction has been signed (while waiting for one of the splice transactions to confirm), at which point the channel isn't quiescent anymore.
The splice is finally terminated when both sides send splice_locked
to indicate that one of the splice transactions reached acceptable depth.
+-------+ +-------+
| |--- splice_init -------------->| |
| A |<--------------- splice_ack ---| B |
| | | |
| |--- tx_add_input ------------->| |
| |<------------- tx_add_input ---| |
| |--- tx_add_input ------------->| |
| |<------------ tx_add_output ---| |
| |--- tx_add_output ------------>| |
| |<-------------- tx_complete ---| |
| |--- tx_add_output ------------>| |
| |<-------------- tx_complete ---| |
| |--- tx_complete -------------->| |
| | | |
| |--- commit_sig --------------->| |
| |<--------------- commit_sig ---| |
| |--- tx_signatures ------------>| |
| |<------------ tx_signatures ---| |
| | | |
| | <RESUME CHANNEL> | |
| | | |
| |--- update_add_htlc ---------->| |
| |--- commit_sig --------------->| |
| |--- commit_sig --------------->| |
| |<----------- revoke_and_ack ---| |
| |<--------------- commit_sig ---| |
| |<--------------- commit_sig ---| |
| |--- revoke_and_ack ----------->| |
| | | |
| | <RBF> | |
| | | |
| |<-------------- tx_init_rbf ---| |
| |--- tx_ack_rbf --------------->| |
| |<------------- tx_add_input ---| |
| |--- tx_add_input ------------->| |
| |<------------- tx_add_input ---| |
| |--- tx_add_output ------------>| |
| |<------------ tx_add_output ---| |
| |--- tx_complete -------------->| |
| |<------------ tx_add_output ---| |
| |--- tx_complete -------------->| |
| |<-------------- tx_complete ---| |
| | | |
| |<--------------- commit_sig ---| |
| |--- commit_sig --------------->| |
| |--- tx_signatures ------------>| |
| |<------------ tx_signatures ---| |
| | | |
| | <RESUME CHANNEL> | |
| | | |
| |--- update_add_htlc ---------->| |
| |--- commit_sig --------------->| |
| |--- commit_sig --------------->| |
| |--- commit_sig --------------->| |
| |<----------- revoke_and_ack ---| |
| |<--------------- commit_sig ---| |
| |<--------------- commit_sig ---| |
| |<--------------- commit_sig ---| |
| |--- revoke_and_ack ----------->| |
| | | |
| | <SPLICE COMPLETION> | |
| | | |
| |--- splice_locked ------------>| |
| |<------------ splice_locked ---| |
| | | |
| | <RESUME CHANNEL> | |
| | | |
| |--- update_add_htlc ---------->| |
| |--- commit_sig --------------->| |
| |<----------- revoke_and_ack ---| |
| |<--------------- commit_sig ---| |
| |--- revoke_and_ack ----------->| |
| | | |
+-------+ +-------+
-
type: 80 (
splice_init) -
data:
- [
channel_id:channel_id] - [
s64:funding_contribution_satoshis] - [
u32:funding_feerate_perkw] - [
u32:locktime] - [
point:funding_pubkey] - [
splice_init_tlvs:tlvs]
- [
-
tlv_stream:splice_init_tlvs -
types:
- type: 2 (
require_confirmed_inputs)
- type: 2 (
funding_contribution_satoshis is the amount the sender is adding to their
channel balance (splice-in) or removing from their channel balance (splice-out).
The sending node:
- MUST NOT send
splice_initif the channel is not quiescent. - MUST NOT send
splice_initif it is not the quiescence initiator. - MUST NOT send
splice_initbefore sending and receivingchannel_ready. - MUST NOT send
splice_initwhile another splice is being negotiated. - MUST NOT send
splice_initif another splice has been negotiated butsplice_lockedhas not been sent and received. - MUST NOT send
splice_initif it has previously sentshutdown. - MUST set
funding_feerate_perkwto the feerate for the splice transaction. - If it is splicing funds out of the channel:
- MUST set
funding_contribution_satoshisto a negative value matching the amount that will be subtracted from its current channel balance.
- MUST set
- If it is splicing funds into the channel:
- MUST set
funding_contribution_satoshisto a positive value matching the amount that will be added to its current channel balance.
- MUST set
- If it requires the receiving node to only use confirmed inputs:
- MUST set
require_confirmed_inputs.
- MUST set
- SHOULD use a different
funding_pubkeythan the one used for the previous funding transaction.
The receiving node:
- If the channel is not quiescent:
- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If the sending node is not the quiescence initiator:
- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If another splice is already being negotiated:
- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If another splice has been negotiated but isn't locked yet:
- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If it has received
shutdown:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If the
funding_feerate_perkwis unacceptable:- MUST respond with
tx_abort.
- MUST respond with
- If
funding_contribution_satoshisis negative and its absolute value is greater than the sending node's current channel balance:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If it accepts the splice attempt:
- MUST respond with
splice_ack.
- MUST respond with
- Otherwise (it rejects the splice):
- MUST respond with
tx_abort.
- MUST respond with
-
type: 81 (
splice_ack) -
data:
- [
channel_id:channel_id] - [
s64:funding_contribution_satoshis] - [
point:funding_pubkey] - [
splice_ack_tlvs:tlvs]
- [
-
tlv_stream:splice_ack_tlvs -
types:
- type: 2 (
require_confirmed_inputs)
- type: 2 (
The sending node:
- SHOULD use a different
funding_pubkeythan the one used for the previous funding transaction. - MAY set
funding_contribution_satoshisto0if they don't want to contribute to the splice. - If it requires the receiving node to only use confirmed inputs:
- MUST set
require_confirmed_inputs.
- MUST set
The receiving node:
- If it has sent
splice_init:- If
funding_contribution_satoshisis negative and its absolute value is greater than the sending node's current channel balance:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If it accepts the splice attempt:
- MUST start an
interactive-txsession to create the splice transaction.
- MUST start an
- Otherwise:
- MUST reject the splice attempt by sending
tx_abort.
- MUST reject the splice attempt by sending
- If
- Otherwise (it has not sent
splice_init):- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
The splice transaction is created using the Interactive Transaction Construction protocol, with the following additional requirements.
The sending node:
- If it is the splice initiator:
- MUST add the current channel input to the splice transaction by
sending
tx_add_inputwithshared_input_txidcontaining thetxidof the previous funding transaction.- MUST NOT include
prevtxfor that shared input. - MUST set
prevtx_voutto the previous funding output index.
- MUST NOT include
- MUST add the current channel input to the splice transaction by
sending
- If the receiver set
require_confirmed_inputsinsplice_init,splice_ack,tx_init_rbfortx_ack_rbf:- MUST NOT send a
tx_add_inputthat contains an unconfirmed input.
- MUST NOT send a
The receiving node:
- If
shared_input_txidis set:- If it doesn't match the
txidof the previous funding transaction:- MUST fail the negotiation by sending
tx_abort.
- MUST fail the negotiation by sending
- If
prevtx_voutdoesn't match the previous funding output index:- MUST fail the negotiation by sending
tx_abort.
- MUST fail the negotiation by sending
- If it doesn't match the
The splice transaction must spend the current channel funding output. The
splice initiator is responsible for adding that input to the transaction,
and pay the fees for its weight. It would be wasteful to transmit the
previous funding transaction in the prevtx field, and wouldn't even
be possible for funding transactions that exceed 65kB, so we only transmit
its txid using the shared_input_txid field.
The sending node:
- If it is the splice initiator:
- MUST send at least one
tx_add_output, which contains the new channel's funding output based on thefunding_pubkeys fromsplice_initandsplice_ack.- MUST set the amount of that
tx_add_outputto the previous channel capacity with thefunding_contribution_satoshiss fromsplice_initandsplice_ackapplied.
- MUST set the amount of that
- MUST send at least one
The splice initiator is responsible for adding the new channel funding output to the transaction and paying the fees for its weight.
The receiving node:
- MUST compute the channel balance for each side by adding their respective
funding_contribution_satoshisto their previous channel balance. - MUST fail the negotiation by sending
tx_abortif:- There is not exactly one input spending the current funding transaction.
- There is not exactly one channel funding output using the funding public
keys and funding contributions from
splice_initandsplice_ack. - This is an RBF attempt and the transaction's total fees is less than the last successfully negotiated splice transaction's fees.
- Either side has added an output other than the channel funding output and the balance for that side is less than the channel reserve that matches the new channel capacity.
If a side does not meet the reserve requirements, that's OK: but if they take
funds out of the channel, they must ensure that they do meet them. If your peer
adds a massive amount to the channel, then you only have to add more reserve if
you want to contribute to the splice (and you can use tx_remove_output and/or
tx_remove_input part-way through if this happens).
After exchanging tx_complete, both peers send commitment_signed to commit
to the splice transaction by creating a commitment transaction spending the
new channel funding output.
The usual commitment_signed
requirements apply with the following additions.
The sending node:
- MUST create a commitment transaction that spends the splice funding output and:
- Adds
funding_contribution_satoshisfromsplice_initandsplice_ackto the main balance of their respective sender. - Uses the same feerate as the existing commitment transaction.
- Uses the same
commitment_numberas the existing commitment transaction.
- Adds
- MUST send signatures for pending HTLCs.
- MUST remember the details of this splice transaction.
The receiving node:
- MUST NOT respond with
revoke_and_ack. - If it has not already transmitted its
commitment_signed:- MUST send
commitment_signed.
- MUST send
- If it should sign first, as specified in the
tx_signaturesrequirements:- MUST send
tx_signatures. - Note that since the initiator sends
tx_add_inputfor the shared input (corresponding to the previous channel output), 100% of the previous channel capacity is attributed to the initiator when computing who must sendtx_signaturesfirst (instead of using each node's previous balance).
- MUST send
On reconnection:
- If
next_fundingmatches the splice transaction:- MUST retransmit
commitment_signed.
- MUST retransmit
Once peers are ready to exchange commitment signatures, they must remember the details of the splice transaction to allow resuming the signatures exchange if a disconnection happens.
The sending node:
- MUST set
shared_input_signatureto a valid ECDSA signature for thetx_add_inputspending the previous channel funding output using thefunding_pubkeythat matches this input.
The receiving node:
- If
shared_input_signatureis not set:- MUST send an
errorand fail the channel.
- MUST send an
- If
shared_input_signatureis not valid or non-compliant with the LOW-S-standard ruleLOWS:- MUST send an
errorand fail the channel.
- MUST send an
- MUST consider the channel no longer quiescent.
On reconnection:
- If
next_fundingmatches the splice transaction:- MUST retransmit
tx_signatures.
- MUST retransmit
Spending the channel funding output requires a signature from both peers. Each peer transmits its own signature, which allows creating a valid witness for the shared input without adding an additional message.
Once tx_signatures have been exchanged, the splice transaction can be
broadcast. The channel is no longer quiescent: normal operation can resume
while waiting for the transaction to confirm and splice_locked messages
to be exchanged.
The sending node:
- MUST NOT send
tx_init_rbfif the channel is not quiescent. - MUST NOT send
tx_init_rbfif it is not the quiescence initiator. - MAY send
tx_init_rbfeven if it is not the splice initiator. - If there are more than 10 pending RBF attempts:
- MUST set a high enough
feerateto ensure quick confirmation.
- MUST set a high enough
- MUST NOT send
tx_init_rbfif it has previously sentsplice_locked. - MUST NOT send
tx_init_rbfifoption_zeroconfhas been negotiated. - MAY set
funding_output_contributionto a different value than thefunding_contribution_satoshisused insplice_initorsplice_ack, or in previous RBF attempts.
The receiving node:
- If the channel is not quiescent:
- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If the sending node is not the quiescence initiator:
- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If another RBF attempt has been created recently:
- SHOULD send
tx_abortto reject this RBF attempt and wait for the previous RBF attempt to confirm.
- SHOULD send
- If there are more than 10 pending RBF attempts and the
feerateis not high enough to ensure quick confirmation:- SHOULD send
tx_abortto reject the RBF attempt.
- SHOULD send
- If the sender previously sent
splice_locked:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If
option_zeroconfhas been negotiated:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
- If
funding_output_contributionis negative and its absolute value is greater than the sending node's current channel balance:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
Splice transactions can be RBF-ed to react to changes in the mempool feerate. We allow both nodes to initiate RBF, because any one of them may want to take this opportunity to splice additional funds into or out of the channel without waiting for the initial splice transaction to confirm.
We limit the number of pending RBF attempts, otherwise we may reach the
batch_size limit defined in start_batch.
We require using a large enough feerate when we've already created many RBF
attempts, and we wait between RBF attempts to allow a previous attempt to
confirm.
Since splice transactions always spend the current channel funding output, the
RBF attempts automatically double-spend each other. We thus disallow RBF when
option_zeroconf has been negotiated, because that creates a risk of losing
funds.
The sending node:
- MAY set
funding_output_contributionto a different value than thefunding_contribution_satoshisused insplice_initorsplice_ack, or in previous RBF attempts.
The receiving node:
- If
funding_output_contributionis negative and its absolute value is greater than the sending node's current channel balance:- MUST send a
warningand close the connection or send anerrorand fail the channel.
- MUST send a
Once splice transactions have been signed but haven't reached acceptable depth, channel operations go back to normal and HTLCs can be exchanged, with the caveat that payments must be valid for all splice transactions.
Nodes keep track of multiple commitment transactions (one for the current funding transaction and one for each splice transaction) and exchange signatures for each of these commitment transactions.
+------------+ +-----------+
| Funding Tx |---+--->| Commit Tx |
+------------+ | +-----------+
| +-----------+ +-----------+
+--->| Splice Tx |----------->| Commit Tx |
| +-----------+ +-----------+
| +---------------+ +-----------+
+--->| Splice RBF #1 |------->| Commit Tx |
| +---------------+ +-----------+
| +---------------+ +-----------+
+--->| Splice RBF #2 |------->| Commit Tx |
+---------------+ +-----------+
The splice completes by exchanging splice_locked messages, at which point
the locked transaction replaces the previous funding transaction.
- type: 77 (
splice_locked) - data:
- [
channel_id:channel_id] - [
sha256:splice_txid]
- [
Each node:
- If any splice transaction reaches acceptable depth:
- MUST send
splice_lockedwith thetxidof that transaction.
- MUST send
- If
option_zeroconfhas been negotiated:- SHOULD send
splice_lockedimmediately after exchangingtx_signatures.
- SHOULD send
The receiving node:
- If
splice_txiddoesn't match any of its pending splice transactions:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
Once a node has sent and received splice_locked:
- If the
splice_txids match:- MUST stop sending
commitment_signedfor RBF attempts and ancestors of this splice transaction. - MAY discard RBF attempts and ancestor transactions.
- If
announce_channelis set for this channel:- MUST send
announcement_signatureswithshort_channel_idmatching this splice transaction.
- MUST send
- MUST stop sending
- If the
splice_txids are for different RBF candidates:- SHOULD ignore the message.
- MAY send an
errorand fail the channel.
If nodes are on a different fork of the blockchain, they may disagree on which
RBF attempt has been confirmed: in that case nodes can either close the channel
or simply ignore splice_locked and wait for one of the forks to eventually
replace the other, at which point both nodes should agree on which RBF attempt
confirmed and exchange splice_locked for the same splice_txid to complete
the splice.
Nodes can negotiate a mutual close of the connection, which unlike a unilateral close, allows them to access their funds immediately and can be negotiated with lower fees.
Closing happens in two stages:
-
one side indicates it wants to clear the channel (and thus will accept no new HTLCs)
-
once all HTLCs are resolved, the final channel close negotiation begins.
+-------+ +-------+ | | shutdown(scriptA1) | | | |--------------------------------------------------------->| | | | shutdown(scriptB1) | | | |<---------------------------------------------------------| | | | | | | | <complete all pending HTLCs> | | | A | .... | B | | | | | | | closing_complete(scriptA1, scriptB1, 1000 sat) | | | |--------------------------------------------------------->| | | | closing_complete(scriptB1, scriptA1, 750 sat) | | | |<---------------------------------------------------------| | | | closing_sig(scriptA1, scriptB1, 1000 sat) | | | |<---------------------------------------------------------| | | | closing_sig(scriptB1, scriptA1, 750 sat) | | | |--------------------------------------------------------->| | | | | | | | <A updates their script> | | | | | | | | closing_complete(scriptA2, scriptB1, 1100 sat) | | | |--------------------------------------------------------->| | | | closing_sig(scriptA2, scriptB1, 1100 sat) | | | |<---------------------------------------------------------| | | | | | | | .... | | | | | | | | <B RBFs their previous tx> | | | | | | | | closing_complete(scriptB1, scriptA2, 850 sat) | | | |<---------------------------------------------------------| | | | closing_sig(scriptB1, scriptA2, 850 sat) | | | |--------------------------------------------------------->| | | | | | | | .... | | | | | | | | <A and B concurrently update their script> | | (*) Note that this is a very rare race condition | | | | | | closing_complete(scriptA3, scriptB1, 1250 sat) | | | |-----------------------------> | | | | closing_complete(scriptB2, scriptA2, 900 sat) | | | | <--------------------------------------| | | | closing_complete | | | | --------------------------->| | | | warning | | (*) B sends a warning because A is not using scriptB2 | | <--------------------------------------| | | | closing_complete | | | |<------------------ | | | | warning | | (*) A sends a warning because B is not using scriptA3 | |--------------------------------------------------------->| | | | warning | | | |<------------------ | | | | | | | | <disconnect> | | (*) A and B reconnect to resolve the race condition | | | | | | channel_reestablish | | | |--------------------------------------------------------->| | | | channel_reestablish | | | |<---------------------------------------------------------| | | | shutdown(scriptA3) | | | |--------------------------------------------------------->| | | | shutdown(scriptB2) | | | |<---------------------------------------------------------| | | | | | | | <A retries with B's latest script> | | | | | | | | closing_complete(scriptA3, scriptB2, 1250 sat) | | | |--------------------------------------------------------->| | | | closing_sig(scriptA3, scriptB2, 1250 sat) | | | |<---------------------------------------------------------| | | | | | | | <B retries with A's latest script> | | | | | | | | closing_complete(scriptB2, scriptA3, 900 sat) | | | |<---------------------------------------------------------| | | | closing_sig(scriptB2, scriptA3, 900 sat) | | | |--------------------------------------------------------->| | | | | | +-------+ +-------+
Either node (or both) can send a shutdown message to initiate closing,
along with the scriptpubkey it wants to be paid to.
- type: 38 (
shutdown) - data:
- [
channel_id:channel_id] - [
u16:len] - [
len*byte:scriptpubkey]
- [
A sending node:
-
if it hasn't sent a
funding_created(if it is a funder) or afunding_signed(if it is a fundee):- MUST NOT send a
shutdown
- MUST NOT send a
-
MAY send a
shutdownbefore achannel_ready, i.e. before the funding transaction has reachedminimum_depth. -
if there are updates pending on the receiving node's commitment transaction:
- MUST NOT send a
shutdown.
- MUST NOT send a
-
MUST NOT send multiple
shutdownmessages. -
MUST NOT send
shutdownif there is a splice transaction that isn't locked yet. -
MUST NOT send an
update_add_htlcafter ashutdown. -
if no HTLCs remain in either commitment transaction (including dust HTLCs) and neither side has a pending
revoke_and_ackto send:- MUST NOT send any
updatemessage after that point.
- MUST NOT send any
-
SHOULD fail to route any HTLC added after it has sent
shutdown. -
if it sent a non-zero-length
shutdown_scriptpubkeyinopen_channeloraccept_channel:- MUST send the same value in
scriptpubkey.
- MUST send the same value in
-
MUST set
scriptpubkeyin one of the following forms:OP_02020-bytes (version 0 pay to witness pubkey hash), OROP_03232-bytes (version 0 pay to witness script hash), OR- if (and only if)
option_shutdown_anysegwitis negotiated:
OP_1throughOP_16inclusive, followed by a single push of 2 to 40 bytes (witness program versions 1 through 16)
- if (and only if)
option_simple_closeis negotiated:
OP_RETURNfollowed by one of:6to75inclusive followed by exactly that many bytes76followed by76to80followed by exactly that many bytes
A receiving node:
- if it hasn't received a
funding_signed(if it is a funder) or afunding_created(if it is a fundee):- SHOULD send an
errorand fail the channel.
- SHOULD send an
- if the
scriptpubkeyis not in one of the above forms:- SHOULD send a
warning.
- SHOULD send a
- if it hasn't sent a
channel_readyyet:- MAY reply to a
shutdownmessage with ashutdown
- MAY reply to a
- once there are no outstanding updates on the peer, UNLESS it has already sent a
shutdown:- MUST reply to a
shutdownmessage with ashutdown
- MUST reply to a
- if both nodes advertised the
option_upfront_shutdown_scriptfeature, and the receiving node received a non-zero-lengthshutdown_scriptpubkeyinopen_channeloraccept_channel, and thatshutdown_scriptpubkeyis not equal toscriptpubkey:- MAY send a
warning. - MUST fail the connection.
- MAY send a
If channel state is always "clean" (no pending changes) when a
shutdown starts, the question of how to behave if it wasn't is avoided:
the sender always sends a commitment_signed first.
As shutdown implies a desire to terminate, it implies that no new
HTLCs will be added or accepted. Once any HTLCs are cleared, there are no commitments
for which a revocation is owed, and all updates are included on both commitment
transactions, the peer may immediately begin closing negotiation, so we ban further
updates to the commitment transaction (in particular, update_fee would be
possible otherwise). However, while there are HTLCs on the commitment transaction,
the initiator may find it desirable to increase the feerate as there may be pending
HTLCs on the commitment which could timeout.
The scriptpubkey forms include only standard segwit forms accepted by
the Bitcoin network, which ensures the resulting transaction will
propagate to miners. However old nodes may send non-segwit scripts, which
may be accepted for backwards-compatibility (with a caveat to force-close
if this output doesn't meet dust relay requirements).
The option_upfront_shutdown_script feature means that the node
wanted to pre-commit to shutdown_scriptpubkey in case it was
compromised somehow. This is a weak commitment (a malevolent
implementation tends to ignore specifications like this one!), but it
provides an incremental improvement in security by requiring the cooperation
of the receiving node to change the scriptpubkey.
The shutdown response requirement implies that the node sends commitment_signed to commit any outstanding changes before replying; however, it could theoretically reconnect instead, which would simply erase all outstanding uncommitted changes.
OP_RETURN is only standard if followed by PUSH opcodes, and the total script
is 83 bytes or less. We are slightly stricter, to only allow a single PUSH, but
there are two forms in script: one which pushes up to 75 bytes, and a longer
one (OP_PUSHDATA1) which is needed for 76-80 bytes.
Once shutdown is complete, the channel is empty of HTLCs, there are no commitments for which a revocation is owed, and all updates are included on both commitments, the final current commitment transactions will have no HTLCs.
If option_simple_close is not negotiated, see Legacy Closing
Negotiation below.
Each peer creates their own closing transaction where they pay the fee, and sends
closing_complete to the other peer with the transaction details. The other peer
simply signs that transaction and sends back closing_sig. Each peer will thus
independently send closing_complete and receive closing_sig, resulting in two
independent (but conflicting) closing transactions being created.
The lesser-paid peer (if either is) can opt to omit their own output from the closing transaction.
This process can be repeated multiple times by sending closing_complete again,
which allows increasing the fees and changing the output script.
-
type: 40 (
closing_complete) -
data:
- [
channel_id:channel_id] - [
u16:closer_scriptpubkey_len] - [
closer_scriptpubkey_len*byte:closer_scriptpubkey] - [
u16:closee_scriptpubkey_len] - [
closee_scriptpubkey_len*byte:closee_scriptpubkey] - [
u64:fee_satoshis] - [
u32:locktime] - [
closing_tlvs:tlvs]
- [
-
type: 41 (
closing_sig) -
data:
- [
channel_id:channel_id] - [
u16:closer_scriptpubkey_len] - [
closer_scriptpubkey_len*byte:closer_scriptpubkey] - [
u16:closee_scriptpubkey_len] - [
closee_scriptpubkey_len*byte:closee_scriptpubkey] - [
u64:fee_satoshis] - [
u32:locktime] - [
closing_tlvs:tlvs]
- [
-
tlv_stream:closing_tlvs -
types:
- type: 1 (
closer_output_only) - data:
- [
signature:sig]
- [
- type: 2 (
closee_output_only) - data:
- [
signature:sig]
- [
- type: 3 (
closer_and_closee_outputs) - data:
- [
signature:sig]
- [
- type: 1 (
Note: the details and requirements for the transaction being signed are in BOLT 3.
An output is dust if the amount is less than the Bitcoin Core Dust Thresholds.
Note: These requirements only apply if option_simple_close is
negotiated, otherwise the requirements are in Legacy Closing
Negotiation.
Both nodes:
- After a
shutdownhas been sent and received, AND no HTLCs remain in either commitment transaction:- SHOULD send a
closing_completemessage.
- SHOULD send a
The sender of closing_complete (aka. "the closer"):
- MUST set
fee_satoshisto a fee less than or equal to its outstanding balance, rounded down to whole satoshis. - MUST set
fee_satoshisso that at least one output is not dust. - MUST set
closer_scriptpubkeyto its desired output script. - MUST set
closee_scriptpubkeyto the last script it received from its peer (fromclosing_completeor from the initialshutdown). - MUST set
locktimeto the desirednLockTimeof the closing transaction. - If the local outstanding balance (in millisatoshi) is less than the remote outstanding balance:
- MUST NOT set
closer_output_only. - MUST set
closee_output_onlyif the local output amount is dust. - MAY set
closee_output_onlyif it considers the local output amount uneconomical AND itscloser_scriptpubkeyis notOP_RETURN.
- MUST NOT set
- Otherwise (not lesser amount, cannot remove its own output):
- MUST NOT set
closee_output_only. - If it considers the local output amount uneconomical:
- MAY send a
closer_scriptpubkeythat is a validOP_RETURNscript. - If it does, the output value MUST be set to zero so that all funds go to fees, as specified in BOLT #3.
- MAY send a
- If the closee's output amount is dust:
- MUST set
closer_output_only. - MUST NOT set
closer_and_closee_outputs.
- MUST set
- Otherwise:
- MUST set both
closer_output_onlyandcloser_and_closee_outputs.
- MUST set both
- MUST NOT set
- MUST generate its closing transaction as specified in BOLT #3.
- MUST set
signaturefields as valid signature using itsfunding_pubkeyof:closer_output_only: closing transaction with only the local ("closer") output.closee_output_only: closing transaction with only the remote ("closee") output.closer_and_closee_outputs: closing transaction with both the closer and closee outputs.
- If it wants to send another
closing_complete(e.g. with a differentfee_satoshisorcloser_scriptpubkey):- MUST wait until it has received
closing_sigfirst. - SHOULD close the connection if it doesn't receive
closing_sig.
- MUST wait until it has received
The receiver of closing_complete (aka. "the closee"):
- If
fee_satoshisis greater than the closer's outstanding balance:- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If
closee_scriptpubkeydoes not match the last script it sent (fromclosing_completeor from the initialshutdown):- SHOULD ignore
closing_complete. - SHOULD send a
warning. - SHOULD close the connection.
- SHOULD ignore
- If
closer_scriptpubkeyis invalid (as detailed in theshutdownrequirements):- SHOULD ignore
closing_complete. - SHOULD send a
warning. - SHOULD close the connection.
- SHOULD ignore
- If
closer_scriptpubkeyis a validOP_RETURNscript:- MUST set the closer's output amount to zero so that all funds go to fees, as specified in BOLT #3.
- MUST generate the remote closing transaction as specified in BOLT #3.
- Select a signature for validation:
- If the local output amount is dust:
- MUST use
closer_output_only.
- MUST use
- Otherwise, if it considers the local output amount uneconomical AND its
closee_scriptpubkeyis notOP_RETURN:- MUST use
closer_output_only.
- MUST use
- Otherwise, if
closer_and_closee_outputsis present:- MUST use
closer_and_closee_outputs.
- MUST use
- Otherwise:
- MUST use
closee_output_only.
- MUST use
- If the local output amount is dust:
- If the selected signature field does not exist:
- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If the signature field is not valid for the corresponding closing transaction specified in BOLT #3:
- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If the signature field is non-compliant with LOW-S-standard ruleLOWS:
- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- MUST sign and broadcast the corresponding closing transaction.
- MUST send
closing_sigwith a single valid signature in the same TLV field as theclosing_complete. - MUST use
closer_scriptpubkeyfor its own futureclosing_completemessages.
The receiver of closing_sig:
- If
closer_scriptpubkey,closee_scriptpubkey,fee_satoshisorlocktimedon't match what was sent inclosing_complete:- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If
tlvsdoes not contain exactly one signature:- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If
tlvsdoes not contain one of the TLV fields sent inclosing_complete:- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If the signature field is not valid for the corresponding closing transaction specified in BOLT #3:
- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- If the signature field is non-compliant with LOW-S-standard ruleLOWS:
- MUST either send a
warningand close the connection, or send anerrorand fail the channel.
- MUST either send a
- otherwise:
- MUST broadcast the corresponding closing transaction.
- MAY send another
closing_complete(e.g. with a differentfee_satoshisorcloser_scriptpubkey).
The close protocol is designed to avoid any failure scenarios caused by fee disagreement, since each side offers to pay its own desired fee.
If one side has less funds than the other, it may choose to omit its own output, and in this case dust MUST be omitted, to ensure that the resulting transaction can be broadcast.
The corner case where fees are so high that both outputs are dust is addressed in two ways: paying
a low fee to avoid the problem, or using an OP_RETURN (which is never "dust"). If one side
chooses to use an OP_RETURN output, its amount must be 0 to ensure that the resulting transaction
can be broadcast.
Note that there is usually no reason to pay a high fee for rapid processing, since an urgent child
could pay the fee on the closing transactions' behalf. If rapid processing is desired and CPFP is
not an option, the closer can RBF its previous closing transactions by sending closing_complete
again.
Sending a new closing_complete message overrides previous ones, so you can negotiate again (even
changing the output address if upfront_shutdown_script was not negotiated). This creates a rare
race condition if both nodes send closing_complete to change their closer_scriptpubkey at the
same time: when that happens, the closing_complete they receive will be using their previous
output script, so they shouldn't sign the corresponding transaction. When that happens, we simply
reconnect, which provides the opportunity for both nodes to send their latest output script in
shutdown and restart the signing flow. We include the closer and closee scripts in closing_sig
to allow our peer to detect a script mismatch and correctly ignore the signatures, which also
helps debugging race conditions.
If the closer proposes a transaction which will not relay (an output is dust, or the fee rate it proposes is too low), it doesn't harm the closee to sign the transaction.
Similarly, if the closer proposes a high fee, it doesn't harm the closee to sign the transaction, as the closer is paying.
There's a slight game where each side would prefer the other side pay the fee, and proposes a minimal fee. If neither side proposes a fee which will relay, the negotiation can occur again, or the final commitment transaction can be spent. In practice, the opener has an incentive to offer a reasonable closing fee, as they would pay the fee for the commitment transaction, which also costs more to spend.
Once shutdown is complete, the channel is empty of HTLCs, there are no commitments
for which a revocation is owed, and all updates are included on both commitments,
the final current commitment transactions will have no HTLCs, and closing fee
negotiation begins: if option_simple_close is negotiated, the section above applies,
otherwise this legacy section applies.
The funder chooses a fee it thinks is fair, and
signs the closing transaction with the scriptpubkey fields from the
shutdown messages (along with its chosen fee) and sends the signature;
the other node then replies similarly, using a fee it thinks is fair. This
exchange continues until both agree on the same fee or when one side fails
the channel.
In the modern method, the funder sends its permissible fee range, and the non-funder has to pick a fee in this range. If the non-funder chooses the same value, negotiation is complete after two messages, otherwise the funder will reply with the same value (completing after three messages).
-
type: 39 (
closing_signed) -
data:
- [
channel_id:channel_id] - [
u64:fee_satoshis] - [
signature:signature] - [
closing_signed_tlvs:tlvs]
- [
-
tlv_stream:closing_signed_tlvs -
types:
- type: 1 (
fee_range) - data:
- [
u64:min_fee_satoshis] - [
u64:max_fee_satoshis]
- [
- type: 1 (
Note: These requirements only apply if option_simple_close is NOT
negotiated, otherwise the requirements Closing Negotiation:
closing_complete and closing_sig apply.
The funding node:
- after
shutdownhas been received, AND no HTLCs remain in either commitment transaction:- SHOULD send a
closing_signedmessage.
- SHOULD send a
The sending node:
- SHOULD set the initial
fee_satoshisaccording to its estimate of cost of inclusion in a block. - SHOULD set
fee_rangeaccording to the minimum and maximum fees it is prepared to pay for a close transaction. - if it doesn't receive a
closing_signedresponse after a reasonable amount of time:- MUST fail the channel
- if it is not the funder:
- SHOULD set
max_fee_satoshisto at least themax_fee_satoshisreceived - SHOULD set
min_fee_satoshisto a fairly low value
- SHOULD set
- MUST set
signatureto the Bitcoin signature of the close transaction, as specified in BOLT #3.
The receiving node:
- if the
signatureis not valid for either variant of closing transaction specified in BOLT #3 OR non-compliant with LOW-S-standard ruleLOWS:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if
fee_satoshisis equal to its previously sentfee_satoshis:- SHOULD sign and broadcast the final closing transaction.
- MAY close the connection.
- if
fee_satoshismatches its previously sentfee_range:- SHOULD use
fee_satoshisto sign and broadcast the final closing transaction - SHOULD reply with a
closing_signedwith the samefee_satoshisvalue if it is different from its previously sentfee_satoshis - MAY close the connection.
- SHOULD use
- if the message contains a
fee_range:- if there is no overlap between that and its own
fee_range:- SHOULD send a warning
- MUST fail the channel if it doesn't receive a satisfying
fee_rangeafter a reasonable amount of time
- otherwise:
- if it is the funder:
- if
fee_satoshisis not in the overlap between the sent and receivedfee_range:- MUST fail the channel
- otherwise:
- MUST reply with the same
fee_satoshis.
- MUST reply with the same
- if
- otherwise (it is not the funder):
- if it has already sent a
closing_signed:- if
fee_satoshisis not the same as the value it sent:- MUST fail the channel
- if
- otherwise:
- MUST propose a
fee_satoshisin the overlap between received and (about-to-be) sentfee_range.
- MUST propose a
- if it has already sent a
- if it is the funder:
- if there is no overlap between that and its own
- otherwise, if
fee_satoshisis not strictly between its last-sentfee_satoshisand its previously-receivedfee_satoshis, UNLESS it has since reconnected:- SHOULD send a
warningand close the connection, or send anerrorand fail the channel.
- SHOULD send a
- otherwise, if the receiver agrees with the fee:
- SHOULD reply with a
closing_signedwith the samefee_satoshisvalue.
- SHOULD reply with a
- otherwise:
- MUST propose a value "strictly between" the received
fee_satoshisand its previously-sentfee_satoshis.
- MUST propose a value "strictly between" the received
The receiving node:
- if one of the outputs in the closing transaction is below the dust limit for its
scriptpubkey(see BOLT 3):- MUST fail the channel
When fee_range is not provided, the "strictly between" requirement ensures
that forward progress is made, even if only by a single satoshi at a time.
To avoid keeping state and to handle the corner case, where fees have shifted
between disconnection and reconnection, negotiation restarts on reconnection.
Note there is limited risk if the closing transaction is delayed, but it will be broadcast very soon; so there is usually no reason to pay a premium for rapid processing.
Note that the non-funder is not paying the fee, so there is no reason for it to have a maximum feerate. It may want a minimum feerate, however, to ensure that the transaction propagates. It can always use CPFP later to speed up confirmation if necessary, so that minimum should be low.
It may happen that the closing transaction doesn't meet bitcoin's default relay
policies (e.g. when using a non-segwit shutdown script for an output below 546
satoshis, which is possible if dust_limit_satoshis is below 546 satoshis).
No funds are at risk when that happens, but the channel must be force-closed as
the closing transaction will likely never reach miners.
Once both nodes have exchanged channel_ready (and optionally announcement_signatures), the channel can be used to make payments via Hashed Time Locked Contracts.
Changes are sent in batches: one or more update_ messages are sent before a
commitment_signed message, as in the following diagram:
+-------+ +-------+
| |--(1)---- update_add_htlc ---->| |
| |--(2)---- update_add_htlc ---->| |
| |<-(3)---- update_add_htlc -----| |
| | | |
| |--(4)--- commitment_signed --->| |
| A |<-(5)---- revoke_and_ack ------| B |
| | | |
| |<-(6)--- commitment_signed ----| |
| |--(7)---- revoke_and_ack ----->| |
| | | |
| |--(8)--- commitment_signed --->| |
| |<-(9)---- revoke_and_ack ------| |
+-------+ +-------+
Counter-intuitively, these updates apply to the other node's
commitment transaction; the node only adds those updates to its own
commitment transaction when the remote node acknowledges it has
applied them via revoke_and_ack.
Thus each update traverses through the following states:
- pending on the receiver
- in the receiver's latest commitment transaction
- ... and the receiver's previous commitment transaction has been revoked, and the update is pending on the sender
- ... and in the sender's latest commitment transaction
- ... and the sender's previous commitment transaction has been revoked
As the two nodes' updates are independent, the two commitment transactions may be out of sync indefinitely. This is not concerning: what matters is whether both sides have irrevocably committed to a particular update or not (the final state, above).
In general, a node offers HTLCs for two reasons: to initiate a payment of its own, or to forward another node's payment. In the forwarding case, care must be taken to ensure the outgoing HTLC cannot be redeemed unless the incoming HTLC can be redeemed. The following requirements ensure this is always true.
The respective addition/removal of an HTLC is considered irrevocably committed when:
- The commitment transaction with/without it is committed to by both nodes, and any previous commitment transaction without/with it has been revoked, OR
- The commitment transaction with/without it has been irreversibly committed to the blockchain.
A node:
- until an incoming HTLC has been irrevocably committed:
- MUST NOT offer the corresponding outgoing HTLC (
update_add_htlc) in response to that incoming HTLC.
- MUST NOT offer the corresponding outgoing HTLC (
- until the removal of an outgoing HTLC is irrevocably committed, OR until the outgoing on-chain HTLC output has been spent via the HTLC-timeout transaction (with sufficient depth):
- MUST NOT fail the incoming HTLC (
update_fail_htlc) that corresponds to that outgoing HTLC.
- MUST NOT fail the incoming HTLC (
- once the
cltv_expiryof an incoming HTLC has been reached, OR ifcltv_expiryminuscurrent_heightis less thancltv_expiry_deltafor the corresponding outgoing HTLC:- MUST fail that incoming HTLC (
update_fail_htlc).
- MUST fail that incoming HTLC (
- if an incoming HTLC's
cltv_expiryis unreasonably far in the future:- SHOULD fail that incoming HTLC (
update_fail_htlc).
- SHOULD fail that incoming HTLC (
- upon receiving an
update_fulfill_htlcfor an outgoing HTLC, OR upon discovering thepayment_preimagefrom an on-chain HTLC spend:- MUST fulfill the incoming HTLC that corresponds to that outgoing HTLC.
In general, one side of the exchange needs to be dealt with before the other. Fulfilling an HTLC is different: knowledge of the preimage is, by definition, irrevocable and the incoming HTLC should be fulfilled as soon as possible to reduce latency.
An HTLC with an unreasonably long expiry is a denial-of-service vector and therefore is not allowed. Note that the exact value of "unreasonable" is currently unclear and may depend on network topology.
Once an HTLC has timed out, it can either be fulfilled or timed-out; care must be taken around this transition, both for offered and received HTLCs.
Consider the following scenario, where A sends an HTLC to B, who forwards to C, who delivers the goods as soon as the payment is received.
-
C needs to be sure that the HTLC from B cannot time out, even if B becomes unresponsive; i.e. C can fulfill the incoming HTLC on-chain before B can time it out on-chain.
-
B needs to be sure that if C fulfills the HTLC from B, it can fulfill the incoming HTLC from A; i.e. B can get the preimage from C and fulfill the incoming HTLC on-chain before A can time it out on-chain.
The critical settings here are the cltv_expiry_delta in
BOLT #7 and the
related min_final_cltv_expiry_delta in BOLT #11.
cltv_expiry_delta is the minimum difference in HTLC CLTV timeouts, in
the forwarding case (B). min_final_cltv_expiry_delta is the minimum difference
between HTLC CLTV timeout and the current block height, for the
terminal case (C).
Note that a node is at risk if it accepts an HTLC in one channel and
offers an HTLC in another channel with too small of a difference between
the CLTV timeouts. For this reason, the cltv_expiry_delta for the
outgoing channel is used as the delta across a node.
The worst-case number of blocks between outgoing and incoming HTLC resolution can be derived, given a few assumptions:
- a worst-case reorganization depth
Rblocks - a grace-period
Gblocks after HTLC timeout before giving up on an unresponsive peer and dropping to chain - a number of blocks
Sbetween transaction broadcast and the transaction being included in a block
The worst case is for a forwarding node (B) that takes the longest possible time to spot the outgoing HTLC fulfillment and also takes the longest possible time to redeem it on-chain:
- The B->C HTLC times out at block
N, and B waitsGblocks until it gives up waiting for C. B or C commits to the blockchain, and B spends HTLC, which takesSblocks to be included. - Bad case: C wins the race (just) and fulfills the HTLC, B only sees
that transaction when it sees block
N+G+S+1. - Worst case: There's reorganization
Rdeep in which C wins and fulfills. B only sees transaction atN+G+S+R. - B now needs to fulfill the incoming A->B HTLC, but A is unresponsive: B waits
Gmore blocks before giving up waiting for A. A or B commits to the blockchain. - Bad case: B sees A's commitment transaction in block
N+G+S+R+G+1and has to spend the HTLC output, which takesSblocks to be mined. - Worst case: there's another reorganization
Rdeep which A uses to spend the commitment transaction, so B sees A's commitment transaction in blockN+G+S+R+G+Rand has to spend the HTLC output, which takesSblocks to be mined. - B's HTLC spend needs to be at least
Rdeep before it times out, otherwise another reorganization could allow A to timeout the transaction.
Thus, the worst case is 3R+2G+2S, assuming R is at least 1. Note that the
chances of three reorganizations in which the other node wins all of them is
low for R of 2 or more. Since high fees are used (and HTLC spends can use
almost arbitrary fees), S should be small during normal operation; although,
given that block times are irregular, empty blocks still occur, fees may vary
greatly, and the fees cannot be bumped on HTLC transactions, S=12 should be
considered a minimum. S is also the parameter that may vary the most under
attack, so a higher value may be desirable when non-negligible amounts are at
risk. The grace period G can be low (1 or 2), as nodes are required to timeout
or fulfill as soon as possible; but if G is too low it increases the risk of
unnecessary channel closure due to networking delays.
There are four values that need be derived:
-
the
cltv_expiry_deltafor channels,3R+2G+2S: if in doubt, acltv_expiry_deltaof at least 34 is reasonable (R=2, G=2, S=12). -
the deadline for offered HTLCs: the deadline after which the channel has to be failed and timed out on-chain. This is
Gblocks after the HTLC'scltv_expiry: 1 or 2 blocks is reasonable. -
the deadline for received HTLCs this node has fulfilled: the deadline after which the channel has to be failed and the HTLC fulfilled on-chain before its
cltv_expiry. See steps 4-7 above, which imply a deadline of2R+G+Sblocks beforecltv_expiry: 18 blocks is reasonable. -
the minimum
cltv_expiryaccepted for terminal payments: the worst case for the terminal node C is2R+G+Sblocks (as, again, steps 1-3 above don't apply). The default in BOLT #11 is 18, which matches this calculation.
An offering node:
- MUST estimate a timeout deadline for each HTLC it offers.
- MUST NOT offer an HTLC with a timeout deadline before its
cltv_expiry. - if an HTLC which it offered is in either node's current
commitment transaction, AND is past this timeout deadline:
- SHOULD send an
errorto the receiving peer (if connected). - MUST fail the channel.
- SHOULD send an
A fulfilling node:
- for each HTLC it is attempting to fulfill:
- MUST estimate a fulfillment deadline.
- MUST fail (and not forward) an HTLC whose fulfillment deadline is already past.
- if an HTLC it has fulfilled is in either node's current commitment
transaction, AND is past this fulfillment deadline:
- SHOULD send an
errorto the offering peer (if connected). - MUST fail the channel.
- SHOULD send an
When an HTLC in a channel is below the "trimmed" threshold in BOLT3 #3, the HTLC cannot be claimed on-chain, instead being turned into additional miner fees if either party unilaterally closes the channel. Because the threshold is per-HTLC, the total exposure to such HTLCs may be substantial if there are many dust HTLCs committed when the channel is force-closed.
This can be exploited in griefing attacks or even in miner-extractable-value attacks, if the malicious entity wins mining capabilities.
The total exposure is given by the following back-of-the-envelope computation:
remote `max_accepted_htlcs` * (`HTLC-success-kiloweight` * `feerate_per_kw` + remote `dust_limit_satoshis`)
+ local `max_accepted_htlcs` * (`HTLC-timeout-kiloweight` * `feerate_per_kw` + remote `dust_limit_satoshis`)
To mitigate this scenario, a max_dust_htlc_exposure_msat threshold can be
applied when sending, forwarding and receiving HTLCs.
A node:
- when receiving an HTLC:
- if the HTLC's
amount_msatis smaller than the remotedust_limit_satoshisplus the HTLC-timeout fee atfeerate_per_kw:- if the
amount_msatplus the dust balance of the remote transaction is greater thanmax_dust_htlc_exposure_msat:- SHOULD fail this HTLC once it's committed
- SHOULD NOT reveal a preimage for this HTLC
- if the
- if the HTLC's
amount_msatis smaller than the localdust_limit_satoshisplus the HTLC-success fee atfeerate_per_kw:- if the
amount_msatplus the dust balance of the local transaction is greater thanmax_dust_htlc_exposure_msat:- SHOULD fail this HTLC once it's committed
- SHOULD NOT reveal a preimage for this HTLC
- if the
- if the HTLC's
- when offering an HTLC:
- if the HTLC's
amount_msatis smaller than the remotedust_limit_satoshisplus the HTLC-success fee atfeerate_per_kw:- if the
amount_msatplus the dust balance of the remote transaction is greater thanmax_dust_htlc_exposure_msat:- SHOULD NOT send this HTLC
- SHOULD fail the corresponding incoming HTLC (if any)
- if the
- if the HTLC's
amount_msatis inferior to the holder'sdust_limit_satoshisplus the HTLC-timeout fee at thefeerate_per_kw:- if the
amount_msatplus the dust balance of the local transaction is greater thanmax_dust_htlc_exposure_msat:- SHOULD NOT send this HTLC
- SHOULD fail the corresponding incoming HTLC (if any)
- if the
- if the HTLC's
The max_dust_htlc_exposure_msat is an upper bound on the trimmed balance from
dust exposure. The exact value used is a matter of node policy.
For channels that don't use option_anchors, an increase of
the feerate_per_kw may trim multiple htlcs from commitment transactions,
which could create a large increase in dust exposure.
Either node can send update_add_htlc to offer an HTLC to the other,
which is redeemable in return for a payment preimage. Amounts are in
millisatoshi, though on-chain enforcement is only possible for whole
satoshi amounts greater than the dust limit (in commitment transactions these are rounded down as
specified in BOLT #3).
The format of the onion_routing_packet portion, which indicates where the payment
is destined, is described in BOLT #4.
-
type: 128 (
update_add_htlc) -
data:
- [
channel_id:channel_id] - [
u64:id] - [
u64:amount_msat] - [
sha256:payment_hash] - [
u32:cltv_expiry] - [
1366*byte:onion_routing_packet]
- [
-
tlv_stream:update_add_htlc_tlvs -
types:
- type: 0 (
blinded_path) - data:
- [
point:path_key]
- [
- type: 0 (
A sending node:
- if it is responsible for paying the Bitcoin fee:
- MUST NOT offer
amount_msatif, after adding that HTLC to its commitment transaction, it cannot pay the fee for either the local or remote commitment transaction at the currentfeerate_per_kwwhile maintaining its channel reserve (see Updating Fees). - if
option_anchorsapplies to this commitment transaction and the sending node is the funder:- MUST be able to additionally pay for
to_local_anchorandto_remote_anchorabove its reserve.
- MUST be able to additionally pay for
- SHOULD NOT offer
amount_msatif, after adding that HTLC to its commitment transaction, its remaining balance doesn't allow it to pay the commitment transaction fee when receiving or sending a future additional non-dust HTLC while maintaining its channel reserve. It is recommended that this "fee spike buffer" can handle twice the currentfeerate_per_kwto ensure predictability between implementations.
- MUST NOT offer
- if it is not responsible for paying the Bitcoin fee:
- SHOULD NOT offer
amount_msatif, once the remote node adds that HTLC to its commitment transaction, it cannot pay the fee for the updated local or remote transaction at the currentfeerate_per_kwwhile maintaining its channel reserve.
- SHOULD NOT offer
- MUST offer
amount_msatgreater than 0. - MUST NOT offer
amount_msatbelow the receiving node'shtlc_minimum_msat - MUST set
cltv_expiryless than 500000000. - if result would be offering more than the remote's
max_accepted_htlcsHTLCs, in the remote commitment transaction:- MUST NOT add an HTLC.
- if the total value of offered HTLCs would exceed the remote's
max_htlc_value_in_flight_msat:- MUST NOT add an HTLC.
- for the first HTLC it offers:
- MUST set
idto 0.
- MUST set
- MUST increase the value of
idby 1 for each successive offer. - if it is relaying a payment inside a blinded route:
- MUST set
path_key(see Route Blinding)
- MUST set
- if a splice is pending:
- MUST ensure that requirements are met for all commmitment transactions.
id MUST NOT be reset to 0 after the update is complete (i.e. after revoke_and_ack has
been received). It MUST continue incrementing instead.
A receiving node:
- receiving an
amount_msatequal to 0, OR less than its ownhtlc_minimum_msat:- SHOULD send a
warningand close the connection, or send anerrorand fail the channel.
- SHOULD send a
- receiving an
amount_msatthat the sending node cannot afford at the currentfeerate_per_kw(while maintaining its channel reserve and anyto_local_anchorandto_remote_anchorcosts):- SHOULD send a
warningand close the connection, or send anerrorand fail the channel.
- SHOULD send a
- if a sending node adds more than receiver
max_accepted_htlcsHTLCs to its local commitment transaction, OR adds more than receivermax_htlc_value_in_flight_msatworth of offered HTLCs to its local commitment transaction:- SHOULD send a
warningand close the connection, or send anerrorand fail the channel.
- SHOULD send a
- if sending node sets
cltv_expiryto greater or equal to 500000000:- SHOULD send a
warningand close the connection, or send anerrorand fail the channel.
- SHOULD send a
- MUST allow multiple HTLCs with the same
payment_hash. - if the sender did not previously acknowledge the commitment of that HTLC:
- MUST ignore a repeated
idvalue after a reconnection.
- MUST ignore a repeated
- if other
idviolations occur:- MAY send a
warningand close the connection, or send anerrorand fail the channel.
- MAY send a
- MUST decrypt
onion_routing_packetas described in Onion Decryption to extract apayload.- MUST use
path_key(if specified). - MUST use
payment_hashasassociated_data.
- MUST use
- If decryption fails, the result is not a valid
payloadTLV, or it contains unknown even types:- MUST respond with an error as detailed in Failure Messages
- Otherwise:
- MUST follow the requirements for the reader of
payloadin Payload Format
- MUST follow the requirements for the reader of
- If a splice is pending:
- MUST ensure that requirements are met for all commmitment transactions.
The onion_routing_packet contains an obfuscated list of hops and instructions for each hop along the path.
It commits to the HTLC by setting the payment_hash as associated data, i.e. includes the payment_hash in the computation of HMACs.
This prevents replay attacks that would reuse a previous onion_routing_packet with a different payment_hash.
Invalid amounts are a clear protocol violation and indicate a breakdown.
If a node did not accept multiple HTLCs with the same payment hash, an attacker could probe to see if a node had an existing HTLC. This requirement, to deal with duplicates, leads to the use of a separate identifier; it's assumed a 64-bit counter never wraps.
Retransmissions of unacknowledged updates are explicitly allowed for reconnection purposes; allowing them at other times simplifies the recipient code (though strict checking may help debugging).
max_accepted_htlcs is limited to 483 to ensure that, even if both
sides send the maximum number of HTLCs, the commitment_signed message will
still be under the maximum message size. It also ensures that
a single penalty transaction can spend the entire commitment transaction,
as calculated in BOLT #5.
cltv_expiry values equal to or greater than 500000000 would indicate a time in
seconds, and the protocol only supports an expiry in blocks.
The node responsible for paying the Bitcoin fee should maintain a "fee spike buffer" on top of its reserve to accommodate a future fee increase. Without this buffer, the node responsible for paying the Bitcoin fee may reach a state where it is unable to send or receive any non-dust HTLC while maintaining its channel reserve (because of the increased weight of the commitment transaction), resulting in a degraded channel. See #728 for more details.
If splicing is supported, there can be more than one commitment transaction at a time: proposed changes must be valid for all of them.
For simplicity, a node can only remove HTLCs added by the other node. There are four reasons for removing an HTLC: the payment preimage is supplied, it has timed out, it has failed to route, or it is malformed.
To supply the preimage:
- type: 130 (
update_fulfill_htlc) - data:
- [
channel_id:channel_id] - [
u64:id] - [
32*byte:payment_preimage]
- [
tlv_stream:update_fulfill_htlc_tlvs- types:
- type: 1 (
attribution_data) - data:
- [
20*u32:htlc_hold_times] - [
210*sha256[..4]:truncated_hmacs]
- [
- type: 1 (
For a timed out or route-failed HTLC:
- type: 131 (
update_fail_htlc) - data:
- [
channel_id:channel_id] - [
u64:id] - [
u16:len] - [
len*byte:reason]
- [
tlv_stream:update_fail_htlc_tlvs- types:
- type: 1 (
attribution_data) - data:
- [
20*u32:htlc_hold_times] - [
210*sha256[..4]:truncated_hmacs]
- [
- type: 1 (
The reason field is an opaque encrypted blob for the benefit of the
original HTLC initiator, as defined in BOLT #4;
however, there's a special malformed failure variant for the case where
the peer couldn't parse it: in this case the current node instead takes action, encrypting
it into a update_fail_htlc for relaying.
For an unparsable HTLC:
- type: 135 (
update_fail_malformed_htlc) - data:
- [
channel_id:channel_id] - [
u64:id] - [
sha256:sha256_of_onion] - [
u16:failure_code]
- [
A node:
- SHOULD remove an HTLC as soon as it can.
- SHOULD fail an HTLC which has timed out.
- until the corresponding HTLC is irrevocably committed in both sides'
commitment transactions:
- MUST NOT send an
update_fulfill_htlc,update_fail_htlc, orupdate_fail_malformed_htlc.
- MUST NOT send an
- When failing an incoming HTLC:
- If
current_path_keyis set in the onion payload and it is not the final node:- MUST send an
update_fail_htlcerror using theinvalid_onion_blindingfailure code for any local or downstream errors. - SHOULD use the
sha256_of_onionof the onion it received. - MAY use an all zero
sha256_of_onion. - SHOULD add a random delay before sending
update_fail_htlc.
- MUST send an
- If
path_keyis set in the incomingupdate_add_htlc:- MUST send an
update_fail_malformed_htlcerror using theinvalid_onion_blindingfailure code for any local or downstream errors. - SHOULD use the
sha256_of_onionof the onion it received. - MAY use an all zero
sha256_of_onion.
- MUST send an
- If
- When supporting
option_attribution_data:- if
path_keyis not set in the incomingupdate_add_htlc:- MUST initialize
attribution_dataand include it inupdate_fail_htlcandupdate_fulfill_htlc. See BOLT04.
- MUST initialize
- if
A receiving node:
- if the
iddoes not correspond to an HTLC in its current commitment transaction:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if the
payment_preimagevalue inupdate_fulfill_htlcdoesn't SHA256 hash to the corresponding HTLCpayment_hash:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if the
BADONIONbit infailure_codeis not set forupdate_fail_malformed_htlc:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if the
sha256_of_onioninupdate_fail_malformed_htlcdoesn't match the onion it sent and is not all zero:- MAY retry or choose an alternate error response.
- otherwise, a receiving node which has an outgoing HTLC canceled by
update_fail_malformed_htlc:- MUST return an error in the
update_fail_htlcsent to the link which originally sent the HTLC, using thefailure_codegiven and setting the data tosha256_of_onion.
- MUST return an error in the
A node that doesn't time out HTLCs risks channel failure (see
cltv_expiry_delta Selection).
A node that sends update_fulfill_htlc, before the sender, is also
committed to the HTLC and risks losing funds.
If the onion is malformed, the upstream node won't be able to extract the shared key to generate a response — hence the special failure message, which makes this node do it.
The node can check that the SHA256 that the upstream is complaining about does match the onion it sent, which may allow it to detect random bit errors. However, without re-checking the actual encrypted packet sent, it won't know whether the error was its own or the remote's; so such detection is left as an option.
Nodes inside a blinded route must use invalid_onion_blinding to avoid
leaking information to senders trying to probe the blinded route.
Multiple channel messages can be grouped together as a single logical message
using the start_batch message.
-
type: 127 (
start_batch) -
data:
- [
channel_id:channel_id] - [
u16:batch_size]
- [
-
tlv_stream:start_batch_tlvs -
types:
- type: 1 (
message_type) - data:
- [
u16:message_type]
- type: 1 (
A sending node:
- MUST set
batch_sizeto a value strictly greater than 1. - MUST set
batch_sizeto a value lower than or equal to 20. - MUST set
message_typeto132(commitment_signedmessage type as defined in Bolt 1). - After sending
start_batch:- MUST send
batch_sizecommitment_signedmessages for the samechannel_id, without any other unrelated messages in-between.
- MUST send
A receiving node:
- If
batch_sizeis not strictly greater than 1:- MUST ignore the
start_batchmessage. - SHOULD send a
warning.
- MUST ignore the
- If
batch_sizeis strictly greater than 20:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- MUST group the next
batch_sizemessages and process them together. - If one of those messages is not for the specified
channel_id:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- If
message_typeis missing or not set to the type forcommitment_signed:- MUST ignore the
start_batchmessage and process the following messages sequentially.
- MUST ignore the
The start_batch message is only used when sending multiple commitment_signed
messages during splicing. We thus narrow the requirements for this specific
scenario: they can be relaxed in the future if we use start_batch for other
features.
We limit the batch_size to 20 elements to protect against excessive queuing
that could be abused to DoS receiving nodes. The start_batch message is only
used for splice RBF attempts so far, which shouldn't need that many attempts
to get transactions confirmed.
When a node has changes for the remote commitment, it can apply them,
sign the resulting transaction (as defined in BOLT #3), and send a
commitment_signed message.
-
type: 132 (
commitment_signed) -
data:
- [
channel_id:channel_id] - [
signature:signature] - [
u16:num_htlcs] - [
num_htlcs*signature:htlc_signature] - [
commitment_signed_tlvs:tlvs]
- [
-
tlv_stream:commitment_signed_tlvs -
types:
- type: 1 (
funding_txid) - data:
- [
sha256:funding_txid]
- type: 1 (
A sending node:
- MUST NOT send a
commitment_signedmessage that does not include any updates. - MAY send a
commitment_signedmessage that only alters the fee. - MAY send a
commitment_signedmessage that doesn't change the commitment transaction aside from the new revocation number (due to dust, identical HTLC replacement, or insignificant or multiple fee changes). - MUST include one
htlc_signaturefor every HTLC transaction corresponding to the ordering of the commitment transaction (see BOLT #3). - MUST set
funding_txidto the funding transaction spent by this commitment transaction. - if it has not recently received a message from the remote node:
- SHOULD use
pingand await the replypongbefore sendingcommitment_signed.
- SHOULD use
- If there are
Npending splice transactions (withNgreater than0):- MUST send
start_batchfirst withbatch_sizeset toN + 1andmessage_typeset to132(commitment_signed). - MUST send
commitment_signedfor the current channel funding output. - MUST send
commitment_signedfor each of the splice transactions. - MUST set
funding_txidin eachcommitment_signedmessage to match the funding transaction spent by that commitment transaction. - MUST NOT send any other message before it has sent the batch of
commitment_signedmessages.
- MUST send
A receiving node:
- once all pending updates are applied:
- if
signatureis not valid for its local commitment transaction OR non-compliant with LOW-S-standard rule LOWS:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if
num_htlcsis not equal to the number of HTLC outputs in the local commitment transaction:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if
- if any
htlc_signatureis not valid for the corresponding HTLC transaction OR non-compliant with LOW-S-standard rule LOWS:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- If there are pending splice transactions and the sending node did not
send
start_batchfollowed by a batch ofcommitment_signedmessages:- MUST send an
errorand fail the channel.
- MUST send an
- If the sending node sent
start_batchand we are processing a batch ofcommitment_signedmessages:- If
funding_txidis missing in one of thecommitment_signedmessages:- MUST send an
errorand fail the channel.
- MUST send an
- If there are pending splice transactions:
- MUST validate each
commitment_signedbased onfunding_txid. - If
commitment_signedis missing for a funding transaction:- MUST send an
errorand fail the channel.
- MUST send an
- Otherwise:
- MUST respond with a
revoke_and_ackmessage.
- MUST respond with a
- MUST validate each
- Otherwise (no pending splice transactions):
- MUST ignore
commitment_signedwherefunding_txiddoes not match the current funding transaction. - If
commitment_signedis missing for the current funding transaction:- MUST send an
errorand fail the channel.
- MUST send an
- Otherwise:
- MUST respond with a
revoke_and_ackmessage.
- MUST respond with a
- MUST ignore
- If
- Otherwise:
- MUST respond with a
revoke_and_ackmessage.
- MUST respond with a
There's little point offering spam updates: it implies a bug.
The num_htlcs field is redundant, but makes the packet length check fully self-contained.
The recommendation to require recent messages recognizes the reality
that networks are unreliable: nodes might not realize their peers are
offline until after sending commitment_signed. Once
commitment_signed is sent, the sender considers itself bound to
those HTLCs, and cannot fail the related incoming HTLCs until the
output HTLCs are fully resolved.
Note that the htlc_signature implicitly enforces the time-lock mechanism in
the case of offered HTLCs being timed out or received HTLCs being spent. This
is done to reduce fees by creating smaller scripts compared to explicitly
stating time-locks on HTLC outputs.
The option_anchors allows HTLC transactions to "bring their own fees" by
attaching other inputs and outputs, hence the modified signature flags.
Splicing requires us to send and receive additional signatures, as we don't
know which (if any) of the splice transactions will end up being the new
channel funding transaction. We use start_batch to send a batch of
commitment_signed messages containing signatures for each of the pending
splice transactions and for the current funding transaction. After sending
splice_locked, we may receive a batch containing obsolete commitment_signed
messages from our peer that they started sending before receiving our
splice_locked: we can safely ignore them by filtering on funding_txid.
Once the recipient of commitment_signed checks the signature and knows
it has a valid new commitment transaction, it replies with the commitment
preimage for the previous commitment transaction in a revoke_and_ack
message.
This message also implicitly serves as an acknowledgment of receipt
of the commitment_signed, so this is a logical time for the commitment_signed sender
to apply (to its own commitment) any pending updates it sent before
that commitment_signed.
The description of key derivation is in BOLT #3.
- type: 133 (
revoke_and_ack) - data:
- [
channel_id:channel_id] - [
32*byte:per_commitment_secret] - [
point:next_per_commitment_point]
- [
A sending node:
- MUST set
per_commitment_secretto the secret used to generate keys for the previous commitment transaction. - MUST set
next_per_commitment_pointto the values for its next commitment transaction. - MUST send a single
revoke_and_ackmessage, even if it is responding to a batch ofcommitment_signedmessages.
A receiving node:
- if
per_commitment_secretis not a valid secret key or does not generate the previousper_commitment_point:- MUST send an
errorand fail the channel.
- MUST send an
- if the
per_commitment_secretwas not generated by the protocol in BOLT #3:- MAY send a
warningand close the connection, or send anerrorand fail the channel.
- MAY send a
A node:
- MUST NOT broadcast old (revoked) commitment transactions,
- Note: doing so will allow the other node to seize all channel funds.
- SHOULD NOT sign commitment transactions, unless it's about to broadcast
them (due to a failed connection),
- Note: this is to reduce the above risk.
An update_fee message is sent by the node which is paying the
Bitcoin fee. Like any update, it's first committed to the receiver's
commitment transaction and then (once acknowledged) committed to the
sender's. Unlike an HTLC, update_fee is never closed but simply
replaced.
There is a possibility of a race, as the recipient can add new HTLCs
before it receives the update_fee. Under this circumstance, the sender may
not be able to afford the fee on its own commitment transaction, once the update_fee
is finally acknowledged by the recipient. In this case, the fee will be less
than the fee rate, as described in BOLT #3.
The exact calculation used for deriving the fee from the fee rate is given in BOLT #3.
- type: 134 (
update_fee) - data:
- [
channel_id:channel_id] - [
u32:feerate_per_kw]
- [
The node responsible for paying the Bitcoin fee:
- SHOULD send
update_feeto ensure the current fee rate is sufficient (by a significant margin) for timely processing of the commitment transaction.
The node not responsible for paying the Bitcoin fee:
- MUST NOT send
update_fee.
A sending node:
- if
option_anchorswas not negotiated:- if the
update_feeincreasesfeerate_per_kw:- if the dust balance of the remote transaction at the updated
feerate_per_kwis greater thanmax_dust_htlc_exposure_msat:- MAY NOT send
update_fee - MAY fail the channel
- MAY NOT send
- if the dust balance of the local transaction at the updated
feerate_per_kwis greater thanmax_dust_htlc_exposure_msat:- MAY NOT send
update_fee - MAY fail the channel
- MAY NOT send
- if the dust balance of the remote transaction at the updated
- if the
- if a splice is pending:
- MUST ensure that requirements are met for all commmitment transactions.
A receiving node:
- if the
update_feeis too low for timely processing, OR is unreasonably large:- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if the sender is not responsible for paying the Bitcoin fee:
- MUST send a
warningand close the connection, or send anerrorand fail the channel.
- MUST send a
- if the sender cannot afford the new fee rate on the receiving node's
current commitment transaction:
- SHOULD send a
warningand close the connection, or send anerrorand fail the channel.- but MAY delay this check until the
update_feeis committed.
- but MAY delay this check until the
- if
option_anchorswas not negotiated:- if the
update_feeincreasesfeerate_per_kw:- if the dust balance of the remote transaction at the updated
feerate_per_kwis greater thenmax_dust_htlc_exposure_msat:- MAY fail the channel
- if the dust balance of the remote transaction at the updated
- if the dust balance of the local transaction at the updated
feerate_per_kwis greater thanmax_dust_htlc_exposure_msat:- MAY fail the channel
- if the
- SHOULD send a
- if a splice is pending:
- MUST ensure that requirements are met for all commmitment transactions.
Bitcoin fees are required for unilateral closes to be effective.
With option_anchors, feerate_per_kw is not as critical anymore to guarantee
confirmation as it was in the legacy commitment format, but it still needs to
be enough to be able to enter the mempool (satisfy min relay fee and mempool
min fee).
For the legacy commitment format, there is no general method for the broadcasting node to use child-pays-for-parent to increase its effective fee.
Given the variance in fees, and the fact that the transaction may be spent in the future, it's a good idea for the fee payer to keep a good margin (say 5x the expected fee requirement) for legacy commitment txes; but, due to differing methods of fee estimation, an exact value is not specified.
Since the fees are currently one-sided (the party which requested the channel creation always pays the fees for the commitment transaction), it's simplest to only allow it to set fee levels; however, as the same fee rate applies to HTLC transactions, the receiving node must also care about the reasonableness of the fee.
If on-chain fees increase while commitments contain many HTLCs that will
be trimmed at the updated feerate, this could overflow the configured
max_dust_htlc_exposure_msat. Whether to close the channel preemptively
or not is left as a matter of node policy.
If splicing is supported, there can be more than one commitment transaction at a time: proposed changes must be valid for all of them.
Because communication transports are unreliable, and may need to be re-established from time to time, the design of the transport has been explicitly separated from the protocol.
Nonetheless, it's assumed our transport is ordered and reliable. Reconnection introduces doubt as to what has been received, so there are explicit acknowledgments at that point.
This is fairly straightforward in the case of channel establishment
and close, where messages have an explicit order, but during normal
operation, acknowledgments of updates are delayed until the
commitment_signed / revoke_and_ack exchange; so it cannot be assumed
that the updates have been received. This also means that the receiving
node only needs to store updates upon receipt of commitment_signed.
Note that messages described in BOLT #7 are
independent of particular channels; their transmission requirements
are covered there, and besides being transmitted after init (as all
messages are), they are independent of requirements here.
-
type: 136 (
channel_reestablish) -
data:
- [
channel_id:channel_id] - [
u64:next_commitment_number] - [
u64:next_revocation_number] - [
32*byte:your_last_per_commitment_secret] - [
point:my_current_per_commitment_point]
- [
-
tlv_stream:channel_reestablish_tlvs -
types:
- type: 1 (
next_funding) - data:
- [
sha256:next_funding_txid] - [
byte:retransmit_flags]
- [
- type: 5 (
my_current_funding_locked) - data:
- [
sha256:my_current_funding_locked_txid] - [
byte:retransmit_flags]
- [
- type: 1 (
next_commitment_number: A commitment number is a 48-bit
incrementing counter for each commitment transaction; counters
are independent for each peer in the channel and start at 0.
They're only explicitly relayed to the other node in the case of
re-establishment, otherwise they are implicit.
The next_funding.retransmit_flags bitfield is used to let the
receiving peer know which messages they must retransmit for the
corresponding next_funding_txid after the reconnection:
| Bit Position | Name |
|---|---|
| 0 | commitment_signed |
The my_current_funding_locked.retransmit_flags bitfield is used
to let our peer know which messages we expect them to retransmit
after the reconnection:
| Bit Position | Name |
|---|---|
| 0 | announcement_signatures |
A funding node:
- upon disconnection:
- if it has broadcast the funding transaction:
- MUST remember the channel for reconnection.
- otherwise:
- SHOULD NOT remember the channel for reconnection.
- if it has broadcast the funding transaction:
A non-funding node:
- upon disconnection:
- if it has sent the
funding_signedmessage:- MUST remember the channel for reconnection.
- otherwise:
- SHOULD NOT remember the channel for reconnection.
- if it has sent the
A node:
- MUST handle continuation of a previous channel on a new encrypted transport.
- upon disconnection:
- MUST reverse any uncommitted updates sent by the other side (i.e. all
messages beginning with
update_for which nocommitment_signedhas been received).- Note: a node MAY have already used the
payment_preimagevalue from theupdate_fulfill_htlc, so the effects ofupdate_fulfill_htlcare not completely reversed.
- Note: a node MAY have already used the
- MUST reverse any uncommitted updates sent by the other side (i.e. all
messages beginning with
- upon reconnection:
- if a channel is in an error state:
- SHOULD retransmit the error packet and ignore any other packets for that channel.
- otherwise:
- MUST transmit
channel_reestablishfor each channel. - MUST wait to receive the other node's
channel_reestablishmessage before sending any other messages for that channel.
- MUST transmit
- if a channel is in an error state:
The sending node:
- MUST set
next_commitment_numberto the commitment number of the nextcommitment_signedit expects to receive. - MUST set
next_revocation_numberto the commitment number of the nextrevoke_and_ackmessage it expects to receive. - MUST set
my_current_per_commitment_pointto a valid point. - if
next_revocation_numberequals 0:- MUST set
your_last_per_commitment_secretto all zeroes
- MUST set
- otherwise:
- MUST set
your_last_per_commitment_secretto the lastper_commitment_secretit received
- MUST set
- if it has sent
commitment_signedfor an interactive transaction construction but it has not receivedtx_signatures:- MUST include the
next_fundingTLV. - MUST set
next_funding_txidto the txid of that interactive transaction. - if it has not received
commitment_signedfor thisnext_funding_txid:- MUST set the
commitment_signedbit inretransmit_flags.
- MUST set the
- MUST include the
- otherwise:
- MUST NOT include the
next_fundingTLV.
- MUST NOT include the
- if
option_splicewas negotiated:- if a splice transaction reached acceptable depth while disconnected:
- MUST include
my_current_funding_lockedwith the txid of the latest such transaction.
- MUST include
- otherwise, if it has already sent
splice_lockedfor any transaction:- MUST include
my_current_funding_lockedwith the txid of the lastsplice_lockedit sent.
- MUST include
- otherwise, if it has already sent
channel_ready:- MUST include
my_current_funding_lockedwith the txid of the channel funding transaction.
- MUST include
- otherwise (it has never sent
channel_readyorsplice_locked):- MUST NOT include
my_current_funding_locked.
- MUST NOT include
- if
my_current_funding_lockedis included:- if
announce_channelis set for this channel:- if it has not received
announcement_signaturesfor that transaction:- MUST set the
announcement_signaturesbit to1inretransmit_flags.
- MUST set the
- if it has not received
- otherwise:
- MUST set the
announcement_signaturesbit to0inretransmit_flags.
- MUST set the
- if
- if a splice transaction reached acceptable depth while disconnected:
A node:
- if
next_commitment_numberis zero:- MUST immediately fail the channel and broadcast any relevant latest commitment transaction.
- if
next_commitment_numberis 1 in both thechannel_reestablishit sent and received, and none of thosechannel_reestablishmessages containmy_current_funding_lockedornext_fundingfor a splice transaction:- MUST retransmit
channel_ready.
- MUST retransmit
- otherwise:
- MUST NOT retransmit
channel_ready, but MAY sendchannel_readywith a differentshort_channel_idaliasfield.
- MUST NOT retransmit
- upon reconnection:
- MUST ignore any redundant
channel_readyit receives.
- MUST ignore any redundant
- if
next_commitment_numberis equal to the commitment number of the lastcommitment_signedmessage the receiving node has sent:- MUST reuse the same commitment number for its next
commitment_signed.
- MUST reuse the same commitment number for its next
- otherwise:
- if
next_commitment_numberis not equal to the commitment number of the nextcommitment_signedthat the receiving node would send:- SHOULD send an
errorand fail the channel.
- SHOULD send an
- if
- if
next_revocation_numberis equal to the commitment number of the lastrevoke_and_ackthe receiving node sent, AND the receiving node hasn't already received aclosing_signed:- MUST re-send the
revoke_and_ack. - if it has previously sent a
commitment_signedthat needs to be retransmitted:- MUST retransmit
revoke_and_ackandcommitment_signedin the same relative order as initially transmitted.
- MUST retransmit
- MUST re-send the
- otherwise:
- if
next_revocation_numberis not equal to 1 greater than the commitment number of the lastrevoke_and_ackthe receiving node has sent:- SHOULD send an
errorand fail the channel.
- SHOULD send an
- if it has not sent
revoke_and_ack, ANDnext_revocation_numberis not equal to 0:- SHOULD send an
errorand fail the channel.
- SHOULD send an
- if
A receiving node:
- MUST ignore
my_current_per_commitment_point, but MAY require it to be a valid point. - if
next_revocation_numberis greater than expected above, ANDyour_last_per_commitment_secretis correct for thatnext_revocation_numberminus 1:- MUST NOT broadcast its commitment transaction.
- SHOULD send an
errorto request the peer to fail the channel.
- otherwise:
- if
your_last_per_commitment_secretdoes not match the expected values:- SHOULD send an
errorand fail the channel.
- SHOULD send an
- if
A receiving node:
- if the
next_fundingTLV is set:- if
next_funding_txidmatches the latest interactive funding transaction:- if it has not received
tx_signaturesfor that funding transaction:- if the
commitment_signedbit is set inretransmit_flags:- MUST retransmit its
commitment_signedfor that funding transaction.
- MUST retransmit its
- if it has already received
commitment_signedand it should sign first, as specified in thetx_signaturesrequirements:- MUST send its
tx_signaturesfor that funding transaction.
- MUST send its
- if the
- if it has already received
tx_signaturesfor that funding transaction:- MUST send its
tx_signaturesfor that funding transaction.
- MUST send its
- if it has not received
- if it also sets
next_fundingin its ownchannel_reestablish, but the values don't match:- MUST send an
errorand fail the channel.
- MUST send an
- otherwise:
- MUST send
tx_abortto let the sending node know that they can forget this funding transaction.
- MUST send
- if
A receiving node:
- if splice transactions are pending and
my_current_funding_lockedmatches one of those splice transactions, for which it hasn't receivedsplice_lockedyet:- MUST process
my_current_funding_lockedas if it was receivingsplice_lockedfor thistxid.
- MUST process
- if
my_current_funding_lockedis included with theannouncement_signaturesbit set in theretransmit_flags:- if
announce_channelis set for this channel and the receiving node is ready to sendannouncement_signaturesfor the corresponding splice transaction:- MUST retransmit
announcement_signatures.
- MUST retransmit
- if
A node:
- MUST NOT assume that previously-transmitted messages were lost,
- if it has sent a previous
commitment_signedmessage:- MUST handle the case where the corresponding commitment transaction is
broadcast at any time by the other side,
- Note: this is particularly important if the node does not simply
retransmit the exact
update_messages as previously sent.
- Note: this is particularly important if the node does not simply
retransmit the exact
- MUST handle the case where the corresponding commitment transaction is
broadcast at any time by the other side,
- if it has sent a previous
- upon reconnection:
- if it has sent a previous
shutdown:- MUST retransmit
shutdown.
- MUST retransmit
- if it has sent a previous
The requirements above ensure that the opening phase is nearly
atomic: if it doesn't complete, it starts again. The only exception
is if the funding_signed message is sent but not received. In
this case, the funder will forget the channel, and presumably open
a new one upon reconnection; meanwhile, the other node will eventually forget
the original channel, due to never receiving channel_ready or seeing
the funding transaction on-chain.
There's no acknowledgment for error, so if a reconnect occurs it's
polite to retransmit before disconnecting again; however, it's not a MUST,
because there are also occasions where a node can simply forget the
channel altogether.
closing_signed also has no acknowledgment so must be retransmitted
upon reconnection (though negotiation restarts on reconnection, so it needs
not be an exact retransmission).
The only acknowledgment for shutdown is closing_signed, so one or the other
needs to be retransmitted.
The handling of updates is similarly atomic: if the commit is not
acknowledged (or wasn't sent) the updates are re-sent. However, it's not
insisted they be identical: they could be in a different order,
involve different fees, or even be missing HTLCs which are now too old
to be added. Requiring they be identical would effectively mean a
write to disk by the sender upon each transmission, whereas the scheme
here encourages a single persistent write to disk for each
commitment_signed sent or received. But if you need to retransmit both a
commitment_signed and a revoke_and_ack, the relative order of these two
must be preserved, otherwise it will lead to a channel closure.
A re-transmittal of revoke_and_ack should never be asked for after a
closing_signed has been received, since that would imply a shutdown has been
completed — which can only occur after the revoke_and_ack has been received
by the remote node.
Note that the next_commitment_number starts at 1, since
commitment number 0 is created during opening.
next_revocation_number will be 0 until the
commitment_signed for commitment number 1 is send and then
the revocation for commitment number 0 is received.
channel_ready is implicitly acknowledged by the start of normal operation,
which is known to have begun after a commitment_signed has been received
(hence, the test for a next_commitment_number greater than 1) or after a
splice transaction has been created.
A node, which has somehow fallen
behind (e.g. has been restored from old backup), can detect that it has fallen
behind. A fallen-behind node must know it cannot broadcast its current
commitment transaction — which would lead to total loss of funds — as the
remote node can prove it knows the revocation preimage. The error returned by
the fallen-behind node should make the other node drop its current commitment
transaction to the chain. The other node should wait for that error to give
the fallen-behind node an opportunity to fix its state first (e.g by restarting
with a different backup).
The next_funding TLV allows peers to finalize the signing steps of an
interactive transaction construction, or safely abort that transaction
if it was not signed by one of the peers, who has thus already removed
it from its state.
my_current_funding_locked is equivalent to sending splice_locked, but is
handled atomically during channel_reestablish (instead of requiring a
retransmission of the splice_locked message). This is useful to avoid race
conditions with channel updates (for more details about this race condition,
see this example).
It handles the case where the splice_locked message was lost during the
disconnection, or when a splice transaction reaches acceptable depth while
peers are disconnected. It also allows requesting a retransmission of the
announcement_signatures message for the latest splice transaction, in case
it wasn't received before disconnecting.
[ FIXME: Insert Author List ]

This work is licensed under a Creative Commons Attribution 4.0 International License.