BOLT 2: Peer Protocol for Channel Management
The peer channel protocol has three phases: establishment, normal operation, and closing.
No reviewsSpecification
BOLT #2: Peer Protocol for Channel Management
The peer channel protocol has three phases: establishment, normal operation, and closing.
Table of Contents
- 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
Channel
Definition of channel_id
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.
channel_id, v2
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.
Rationale
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
Interactive transaction construction allows two peers to collaboratively build a transaction for broadcast. This protocol is the foundation for dual-funded channels establishment (v2).
Set-Up and Vocabulary
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.
Fee Responsibility
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.
Overview
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.
initiator only
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 --->| |
+-------+ +-------+
initiator and non-initiator
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 ------| |
+-------+ +-------+
The tx_add_input Message
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 (
Requirements
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
Rationale
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.
Liquidity griefing
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
The tx_add_output Message
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]
- [
Requirements
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
Rationale
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.
The tx_remove_input and tx_remove_output Messages
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]
- [
[Content truncated — view full spec at source]
Discussion (0 threads)
No discussion yet. Be the first to comment.