From f53ca2301232db780843e894f55d95d512f297f9 Mon Sep 17 00:00:00 2001 From: niftynei Date: Tue, 2 Mar 2021 21:10:33 -0600 Subject: [PATCH] interactive-tx: Add dual-funding flow, using the interactive tx protocol This commit adds the interactive transaction construction protcol, as well as the first practical example of using it, v2 of channel establishment. Note that for v2 we also update the channel_id, which now uses the hash of the revocation_basepoints. We move away from using the funding transaction id, as the introduction of RBF* makes it such that a single channel may have many funding transaction id's over the course of its lifetime. *Later, also splicing --- .aspell.en.pws | 21 ++ 01-messaging.md | 4 +- 02-peer-protocol.md | 702 ++++++++++++++++++++++++++++++++++++++++++++ 03-transactions.md | 347 +++++++++++++++++++++- 09-features.md | 1 + tools/spellcheck.sh | 3 +- 6 files changed, 1074 insertions(+), 4 deletions(-) diff --git a/.aspell.en.pws b/.aspell.en.pws index c9e3a0206..d34122a8e 100644 --- a/.aspell.en.pws +++ b/.aspell.en.pws @@ -23,6 +23,7 @@ nhops retransmitted dev tradeoff +kiloweight mixHeader uint hopsData @@ -115,6 +116,17 @@ delayedsig hopDataSize I'th segwit +RBF +accepter +accepter's +subtype +redeemScript +scriptSig +utxo +scriptPubKey +scriptPubKeys +scriptlen +sats htlc htlcs ChaCha @@ -386,3 +398,12 @@ csv CHECKSIGVERIFY IFDUP sats +workflow +PUSHDATA +prev +vout +rbf +standardness +perkw +prevtx +ints diff --git a/01-messaging.md b/01-messaging.md index 678393e1b..ea928c20c 100644 --- a/01-messaging.md +++ b/01-messaging.md @@ -316,11 +316,11 @@ The 2-byte `len` field indicates the number of bytes in the immediately followin The channel is referred to by `channel_id`, unless `channel_id` is 0 (i.e. all bytes are 0), in which case it refers to all channels. -The funding node: +The funding node using channel establishment `open_channel`: - for all error messages sent before (and including) the `funding_created` message: - MUST use `temporary_channel_id` in lieu of `channel_id`. -The fundee node: +The fundee node using channel establishment v1 (`accept_channel`): - for all error messages sent before (and not including) the `funding_signed` message: - MUST use `temporary_channel_id` in lieu of `channel_id`. diff --git a/02-peer-protocol.md b/02-peer-protocol.md index f9dc39351..fbc56c82d 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -7,12 +7,29 @@ operation, and closing. * [Channel](#channel) * [Definition of `channel_id`](#definition-of-channel_id) + * [Interactive Transaction Construction](#interactive-transaction-construction) + * [Set-Up and Vocabulary](#set-up-and-vocabulary) + * [Fee Responsibility](#fee-responsibility) + * [Overview](#overview) + * [The `tx_add_input` Message](#the-tx_add_input-message) + * [The `tx_add_output` Message](#the-tx_add_output-message) + * [The `tx_remove_input` and `tx_remote_output` Messages](#the-tx_remove_input-and-tx_remove_output-messages) + * [The `tx_complete` Message](#the-tx_complete-message) + * [The `tx_signatures` Message](#the-tx_signatures-message) * [Channel Establishment](#channel-establishment) * [The `open_channel` Message](#the-open_channel-message) * [The `accept_channel` Message](#the-accept_channel-message) * [The `funding_created` Message](#the-funding_created-message) * [The `funding_signed` Message](#the-funding_signed-message) * [The `funding_locked` Message](#the-funding_locked-message) + * [Channel Establishment v2](#channel-establishment-v2) + * [The `open_channel2` Message](#the-open_channel2-message) + * [The `accept_channel2` Message](#the-accept_channel2-message) + * [Funding Composition](#funding-composition) + * [The `commitment_signed` Message](#the-commitment_signed-message) + * [Sharing funding signatures: `tx_signatures`](#sharing-funding-signatures-tx_signatures) + * [The `init_rbf` Message](#the-init_rbf-message) + * [The `ack_rbf` Message](#the-ack_rbf-message) * [Channel Close](#channel-close) * [Closing Initiation: `shutdown`](#closing-initiation-shutdown) * [Closing Negotiation: `closing_signed`](#closing-negotiation-closing_signed) @@ -50,10 +67,361 @@ 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. +The basepoints are compact DER-encoded public keys. + +If the peer's revocation basepoint is unknown (e.g. `open_channel2`), +a temporary `channel_id` should be found by using a zeroed out basepoint for the unknown peer. + +#### Rationale +These values must be remembered by both peers for correct operation anyway. +They're known from the first exchange of messages, obviating the need for +a `temporary_channel_id`. Finally, by mixing information from both sides, +they avoid `channel_id` collisions. + + +## 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`; for a close, the *initiator* sends `shutdown`. + +The protocol makes the following assumptions: + +- The `feerate` for the transaction is known. +- The `dust_limit` for the transaction is known. +- The `nLocktime` for the transaction has been negotiated, or is established + via convention. +- The transaction version is 2. + +### 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_rm_input`, `tx_rm_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`. + +Once peers have exchanged consecutive `tx_complete`s, 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_id`s are generally chosen randomly, to maintain consistent transaction +ordering across all peer sessions, it is simplest to invert the bottom-bit of +received `serial_id` before forwarding them to other peers. + +Here are a few example exchanges. + +#### *initiator* only + +A, *initiator* has two inputs and an output (the funding output). +B, the *non-initiator* has nothing to contribute. +n + + +-------+ +-------+ + | |--(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_add_output --| | + | |--(8)- tx_rm_output -->| | + | |<-(9)- tx_complete ----| | + | |--(10) tx_complete --->| | + +-------+ +-------+ + + +### The `tx_add_input` Message + +This message contains a transaction input. + +1. type: 66 (`tx_add_input`) +2. data: + * [`channel_id`:`channel_id`] + * [`u64`:`serial_id`] + * [`u16`:`prevtx_len`] + * [`prevtx_len*byte`:`prevtx`] + * [`u32`:`prevtx_vout`] + * [`u32`:`sequence`] + * [`u16`:`script_sig_len`] + * [`script_sig_len*byte`:`script_sig`] + +#### Requirements + +The sending node: + - MUST add all sent inputs to the transaction + - MUST use a unique `serial_id` for each input currently added to the + transaction + - MUST NOT re-transmit inputs it has received from the peer + - if is the *initiator*: + - MUST send even `serial_id`s + - if is the *non-initiator*: + - MUST send odd `serial_id`s + +The receiving node: + - MUST add all received inputs to the transaction + - MUST fail the negotiation if: + - the `prevtx` and `prevtx_vout` are identical to a previously added + (and not removed) input's + - `prevtx` is not a valid transaction + - `prevtx_vout` is greater or equal to the number of outputs on `prevtx` + - the `prevtx_out` input of `prevtx` is not an `OP_0` to `OP_16` + followed by a single push + - the `serial_id` is already included in the transaction + - the `serial_id` has the wrong parity + - if has received 4096 `tx_add_input` messages 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 are sorted by `serial_id`. + +`prevtx_tx` is the serialized transaction that contains the output +this input spends. Used to verify that the input is non-malleable. + +`prevtx_vout` is the index of the output being spent. + +`sequence` is the sequence number of this input. Must be less than +4294967294 (0xFFFFFFFE). See BIP125. + +`script_sig` is the scriptSig for the input, with length omitted. +The `script_sig` for non-P2SH-wrapped inputs will be an empty byte. + +### The `tx_add_output` Message + +This message adds a transaction output. + +1. type: 67 (`tx_add_output`) +2. 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_id`s + - if is the *non-initiator*: + - MUST send odd `serial_id`s + +The receiving node: + - MUST add the specified output to the transaction + - MUST accept P2SH, P2WSH, P2WPKH, P2PKH `script`s + - MAY fail the negotiation if `script` is non-standard + - MUST fail the negotiation if: + - the `serial_id` is already included in the transaction + - the `serial_id` has the wrong parity + - it has received 4096 `tx_add_output` messages during this negotiation + - the `sats` amount is less than or equal to the `dust_limit` + + +#### 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 are sorted by `serial_id`. + +`sats` is the satoshi value of the output. + +`script` is the scriptPubKey for the output. The length is omitted. +It's left undefined if you accept other standard outputs such as `OP_RETURN` +or implement stricter checks on standardness. + + +### The `tx_remove_input` and `tx_remove_output` Messages +These message removes an input from the transaction. + +1. type: 68 (`tx_remove_input`) +2. data: + * [`channel_id`:`channel_id`] + * [`u64`:`serial_id`] + +This message removes an output from the transaction. + +1. type: 69 (`tx_remove_output`) +2. data: + * [`channel_id`:`channel_id`] + * [`u64`:`serial_id`] + +#### Requirements + +The sending node: + - MUST NOT send a `tx_remove` with a `serial_id` it did not add + to the transaction or has already 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_id` was not added by the + sender + - the `serial_id` does not correspond to a currently added input (or output) + + +### The `tx_complete` Message + +This message signals the conclusion of a peer's transaction +contributions. + +1. type: 70 (`tx_complete`) +2. data: + * [`channel_id`:`channel_id`] + + +#### Requirements + +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 + - the peer's paid feerate does not meet or exceed the agreed `feerate`, + (based on the `minimum fee`). + - if is the *non-initiator*: + - the *initiator*'s fees do not cover the `common` fields + - there are more than 252 inputs + - there are more than 252 outputs + +#### Rationale +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](03-transactions.md#calculating-fees-for-collaborative-transaction-construction). + +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). + + +### The `tx_signatures` Message + +1. type: 71 (`tx_signatures`) +2. data: + * [`channel_id`:`channel_id`] + * [`sha256`:`txid`] + * [`u16`:`num_witnesses`] + * [`num_witnesses*witness_stack`:`witness_stack`] + +1. subtype: `witness_stack` +2. data: + * [`u16`:`num_input_witness`] + * [`num_input_witness*witness_element`:`witness_element`] + +1. subtype: `witness_element` +2. data: + * [`u16`:`len`] + * [`len*byte`:`witness`] + + +#### Requirements +The sending node: + - MUST order the `witness_stack`s by the `serial_id` of the input they + correspond to + - number of `witness_stack`s MUST equal the number of inputs they added + +The receiving node: + - MUST fail the negotiation if: + - the message contains an empty `witness_stack` + - the number of `witness_stack`s does not equal the number of inputs + added by the sending node + - the `txid` does not match the txid of the transaction + - MUST fail the channel if: + - the `witness_stack` weight lowers the effective `feerate` + below the agreed upon transaction `feerate` + - SHOULD apply the `witness`es to the transaction and broadcast it + - MUST reply with their `tx_signatures` if not already transmitted + + +#### Rationale +`witness` is the data for a witness element in a witness stack. +Witness elements should *not* include their length. + +Witness data must be sorted according to the `serial_id` of +the corresponding input. + +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, e.g. a multisig witness stack whose weight exceeds 110. +If the fees paid by the peer (inputs - outputs) does not meet or exceed +the pre-established `feerate`, the receiving peer SHOULD immediately +fail the channel by broadcasting their commitment transaction. + ## Channel Establishment After authenticating and initializing a connection ([BOLT #8](08-transport.md) and [BOLT #1](01-messaging.md#the-init-message), respectively), channel establishment may begin. + +There are two pathways for establishing a channel, a legacy version presented here, +and a second version ([below](#channel-establishment-v2)). 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 @@ -230,6 +598,8 @@ The receiving node MUST: `open_channel`, BUT before receiving a `funding_created` message: - accept a new `open_channel` message. - discard the previous `open_channel` message. + - if `option_dual_fund` has been negotiated: + - fail the channel. The receiving node MAY fail the channel if: - `announce_channel` is `false` (`0`), yet it wishes to publicly announce the channel. @@ -445,6 +815,338 @@ 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. +If an RBF negotiation is in progress when a `funding_locked` message is +exchanged, the negotiation must be abandoned. + +## Channel Establishment v2 + +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. + +The protocol is also expanded to include a mechanism for initiating RBF. + + +-------+ +-------+ + | |--(1)--- open_channel2 ----->| | + | |<-(2)--- accept_channel2 -----| | + | | | | + --->| | | | + | | | | | + | | |--(3)-- commitment_signed -->| | + | | |<-(4)-- commitment_signed ---| | + | | A | | B | + | | |<-(5)-- tx_signatures -------| | + | | |--(6)-- tx_signatures ------>| | + | | | | | + | | |--(a)--- init_rbf ----------->| | + ----| |<-(b)--- ack_rbf ------------| | + | | | | + | |--(7)--- funding_locked ----->| | +n- + | |<-(8)--- funding_locked ------| | + +-------+ +-------+ + + - where node A is *opener*/*initiator* and node B is + *accepter*/*non-initiator* + +### The `open_channel2` Message + +This message initiates the v2 channel establishment workflow. + +1. type: 64 (`open_channel2`) +2. data: + * [`chain_hash`:`chain_hash`] + * [`channel_id`:`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`] + * [`byte`:`channel_flags`] + * [`opening_tlvs`:`tlvs`] + + +1. `tlv_stream`: `opening_tlvs` +2. types: + 1. type: 1 (`option_upfront_shutdown_script`) + 2. data: + * [`u16`:`shutdown_len`] + * [`shutdown_len*byte`:`shutdown_scriptpubkey`] + + +Rationale and Requirements are the same as for [`open_channel`](#the-open_channel-message), with the following additions: + +#### Requirements: + +If nodes have negotiated `option_dual_fund`: + - the opening node: + - MUST NOT send `open_channel` + +The sending node: + - MUST set `funding_feerate_perkw` to the feerate for this transaction + - MUST ensure `temporary_channel_id` is unique from any + other channel ID with the same peer. + +The receiving node: + - MAY fail the negotiation if: + - the `locktime` is unacceptable + - the `funding_feerate_per_kw` is unacceptable + +#### Rationale +`channel_id` for the `open_channel2` MUST be derived using a zero-d 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](03-transactions.md#appendix-f-dual-funded-transaction-test-vectors). + +`locktime` is the locktime for the funding transaction. + +The receiving node, if the `locktime` or `feerate_funding_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. + +### The `accept_channel2` Message + +This message contains information about a node and indicates its +acceptance of the new channel. + +1. type: 65 (`accept_channel2`) +2. data: + * [`channel_id`:`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`] + * [`accept_tlvs`:`tlvs`] + +1. `tlv_stream`: `accept_tlvs` +2. types: + 1. type: 1 (`option_upfront_shutdown_script`) + 2. data: + * [`u16`:`shutdown_len`] + * [`shutdown_len*byte`:`shutdown_scriptpubkey`] + + +Rationale and Requirements are the same as listed above, +for [`accept_channel`](#the-accept_channel-message) with the following +additions. + +#### Requirements: + +The accepting node: + - MAY respond with a `funding_satoshis` value of zero. + +#### Rationale + +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 +Funding composition for channel establishment v2 makes use of the +[Interactive Transaction Construction](#interactive-transaction-construction) +protocol, with the following additional caveats. + + +#### The `tx_add_input` Message + +No additional caveats or requirements. + + +#### The `tx_add_output` Message +##### Requirements +The sending node: + - if is the *opener*: + - MUST send at least one `tx_add_output`, which contains the + channel's funding output + +##### Rationale +The channel funding output must be added by the *opener*, who pays its fees. + + +#### The `tx_complete` Message + +Upon receipt of consecutive `tx_complete`s, 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_satoshis` and `accept_channel2`. + `funding_satoshis` + - the value of the funding output is less than the `dust_limit` + - if 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 a common input with all previous + funding transactions + +### The `commitment_signed` Message + +This message is exchanged by both peers. It contains the signatures for +the first commitment transaction. + +Rationale and Requirements are the same as listed below, +for [`commitment_signed`](#commiting-updates-so-far-commitment_signed) with the following additions. + +#### Requirements + +The sending node: + - MUST send zero HTLC's. + +The receiving node: + - if the message has one or more HTLC's: + - MUST fail the negotiation + - if it has not already transmitted its `commitment_signed`: + - MUST send `commitment_signed` + - Otherwise: + - MUST send `tx_signatures` + +#### Rationale + +The first commitment transaction has no HTLC's. + + +### Sharing funding signatures: `tx_signatures` + +After a valid `commitment_signature` has been received +from the peer and a `commitment_signature` has been sent, a peer: + - MUST transmit a [`tx_signatures` message](#the-tx_signatures-message) with their signatures for + the funding transaction + + +#### Requirements +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_signed` message: + - MUST NOT send a `tx_signatures` message + +The receiving node: + - if the received `witness_stack` weight results in the peer's + paid feerate falling below the *opener*'s feerate for the funding + transaction: + - SHOULD broadcast their commitment transaction, closing the channel. + - SHOULD apply `witness`es to the funding transaction and broadcast it + - if has already sent or received a `funding_locked` message for this + channel: + - MUST ignore this message + +#### Rationale +A peer sends their `tx_signatures` as soon as they have received a valid +`commitments_signed` message. + +The channel should be preemptively closed in the case where a peer provides +valid witness data that causes their paid feerate to fall beneath the +`open_channel2.funding_feerate_perkw` rate. This penalizes the peer +for underpayment of fees. + + +### The `init_rbf` Message + +This message initiates a replacement of a broadcast funding transaction. + +1. type: 72 (`init_rbf`) +2. data: + * [`channel_id`:`channel_id`] + * [`u64`:`funding_satoshis`] + * [`u32`:`locktime`] + * [`byte`:`fee_step`] + +#### Requirements + +The sender: + - MUST have sent `open_channel2` + - MUST set `fee_step` greater than zero and greater than any prior `fee_step` + - MUST NOT have sent or received a `funding_locked` message. + +The recipient: + - MUST respond with either an error or an `ack_rbf` message. + - MUST fail the negotiation if: + - the `fee_step` is not greater than the last successfully negotiated + `init_rbf` attempt or `one` if no prior successful `init_rbf` has + been received + - they have already sent or received `funding_locked` + - MAY fail the negotiation for any reason + +#### Rationale +`fee_step` is an integer value, which specifies the `feerate` for this +funding transaction, as a rate of increase above the `open_channel2`. +`funding_feerate_perkw`. + +The effective `funding_feerate_perkw` for this RBF attempt +if calculated as 1.25^`fee_step` * `funding_feerate_perkw`. +E.g. if `feerate_per_kw_funding` is 512 and the `fee_step` is 1, +the effective `feerate` for this RBF attempt is 512 + 512 / 4 or 640 sat/kw. +A `fee_step` 2 would be `1.25^2 * 512` (or 640 + 640 / 4), 800 sat/kw. + +If a valid `funding_locked` message is received in the middle of an +RBF attempt, the attempt MUST be abandoned. + +### The `ack_rbf` Message + +1. type: 73 (`ack_rbf`) +2. data: + * [`channel_id`:`channel_id`] + * [`u64`:`funding_satoshis`] + +#### Requirements + +The sender: + - MUST NOT have sent or received a `funding_locked` message + +The recipient: + - MUST either fail the negotiation or transmit a `tx_add_input` message + +#### Rationale +`funding_satoshis` is the amount of satoshis that this peer will +contribute to the funding output. Note that this may be different than +the amount transmitted in either `accept_channel2`.`funding_satoshis` or +any previous `ack_rbf`.`funding_satoshis`, as the amount the *accepter* +wishes to commit to the funding output may change. + +It's recommended that a peer, rather than fail the RBF negotiation due to +a large feerate change, instead sets their `funding_satoshis` to zero, +and decline to participate further in the channel funding. + ## Channel Close Nodes can negotiate a mutual close of the connection, which unlike a diff --git a/03-transactions.md b/03-transactions.md index 43b7ed1cd..3e042d277 100644 --- a/03-transactions.md +++ b/03-transactions.md @@ -37,6 +37,7 @@ This details the exact format of on-chain transactions, which both sides need to * [Storage Tests](#storage-tests) * [Appendix E: Key Derivation Test Vectors](#appendix-e-key-derivation-test-vectors) * [Appendix F: Commitment and HTLC Transaction Test Vectors (anchors)](#appendix-f-commitment-and-htlc-transaction-test-vectors-anchors) + * [Appendix G: Dual Funded Transaction Test Vectors](#appendix-f-dual-funded-transaction-test-vectors) * [References](#references) * [Authors](#authors) @@ -477,6 +478,14 @@ A node: - if the resulting fee rate is too low: - MAY fail the channel. + +### Calculating Fees for Collaborative Transactions + +For transactions constructed using the [interactive protocol](02-peer-protocol.md#interactive-transaction-construction), +fees are paid by each party to the transaction, at `feerate` determined during the +initiation, with the initiator covering the fees for the common transaction fields. + + ## Commitment Transaction Construction This section ties the previous sections together to detail the @@ -710,6 +719,104 @@ at each bucket is a prefix of the desired index. # Appendix A: Expected Weights +## Expected Weight of the Funding Transaction (v2 Channel Establishment) + +The *expected weight* of a funding transaction is calculated as follows: + + inputs: 40 bytes + var_int + `scriptlen` + - previous_out_point: 36 bytes + - hash: 32 bytes + - index: 4 bytes + - var_int: ? bytes (dependent on `scriptlen`) + - script_sig: `scriptlen` + - witness <---- Cost for "witness" data calculated separately. + - sequence: 4 bytes + + non_funding_outputs: 8 bytes + var_int + `scriptlen` + - value: 8 bytes + - var_int: ? bytes (dependent on `scriptlen`) + - script_sig: `scriptlen` + + funding_output: 43 bytes + - value: 8 bytes + - var_int: 1 byte + - script: 34 bytes + - OP_0: 1 byte + - PUSHDATA(32-byte-hash): 33 bytes + +Multiplying non-witness data by 4 results in a weight of: + + // transaction_fields = 10 (version, input count, output count, locktime) + // segwit_fields = 2 (marker + flag) + // funding_transaction = 43 + num_inputs * 40 + num_outputs * 8 + // + sum(scriptlen) + sum(var_ints) + + funding_transaction_weight = 4 * (funding_transaction + transaction_fields) + segwit_fields + + witness_weight = sum(max_witness_len) + + overall_weight = funding_transaction_weight + witness_weight + +### Calculating Fees for Collaborative Transaction Construction + +Every participant in a collaborative transaction covers the fees for +their own inputs and outputs. The initiator also provides funds to +cover for the common transaction fields. + +Upon successful exchange of `tx_complete` messages, each peer must at +least cover a minimum estimated fee. Here is how to calculate the minimum +fee for each participant. + +The minimum witness weight for an input is 110. + +In the following, the initiator has provided one input (P2WPKH), one change output +(P2WPKH), and the funding output. The contributor has provided two +inputs (P2WPKH) and two change outputs (P2WPKH). + +Assuming a `feerate` of 253 per kiloweight, the initiator's minimum fee is +calculated as follows. Note that the feerate is rounded down to the nearest satoshi. + + initiator_weight = transaction_fields * 4 + + segwit_fields + + p2wpkh_input * 4 + + funding_output * 4 + + p2wpkh_output * 4 + + input_count * 110 (minimum witness weight) + + initiator_weight = 10 * 4 + + 2 + + 41 * 4 + + 43 * 4 + + 31 * 4 + + 107 + + initiator_weight = 612 + + initiator_fees = initiator_weight * feerate + initiator_fees = 612 * 253 / 1000 + initiator_fees = 154 sats + +The contributor's minimum fee is calculated as follows. + + contributor_weight = 2 * p2wpkh_input * 4 + + 2 * p2wpkh_output * 4 + + input_count * 110 (minimum witness weight) + + contributor_weight = 2 * 41 * 4 + + 2 * 31 * 4 + + 2 * 110 + + contributor_weight = 796 + + contributor_fees = contributor_weight * feerate + contributor_fees = 796 * 253 / 1000 + contributor_fees = 201 sats + + +This is an estimated fee. The peer MUST at least contribute the estimated rate, +and MUST exceed the minimum fee in the case that their witness weight is greater +than the estimated weight of 110 per input. + + ## Expected Weight of the Commitment Transaction The *expected weight* of a commitment transaction is calculated as follows: @@ -1006,7 +1113,7 @@ The resulting funding transaction is: In the following: - *local* transactions are considered, which implies that all payments to *local* are delayed. - - It's assumed that *local* is the funder. + - It's assumed that *local* is the opener. - Private keys are displayed as 32 bytes plus a trailing 1 (Bitcoin's convention for "compressed" private keys, i.e. keys for which the public key is compressed). - Transaction signatures are all deterministic, using RFC6979 (using HMAC-SHA256). @@ -1953,6 +2060,244 @@ before subtraction of: "RemoteSigHex": "30450221008fd5dbff02e4b59020d4cd23a3c30d3e287065fda75a0a09b402980adf68ccda022001e0b8b620cd915ddff11f1de32addf23d81d51b90e6841b2cb8dcaf3faa5ecf" } ] + +# Appendix G: Dual Funded Transaction Test Vectors + +## Funding Transaction Construction +### Preliminaries: + +``` +Genesis block 0: +0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000 + +Block 1:0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910ff86fd1d0db3ac5a72df968622f31e6b5e6566a09e29206d7c7a55df90e181de8be86815cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a0100000017a914113ca7e584fe1575b6fc39abae991529f66eda58870000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000 +Coinbase address pubkey: 2MtpN8zCxTp8AWSg7VBjBX7vU6x73bVCKP8 +Coinbase address privkey: cPxFtfE1w3ptFnsZvvFeWji21kTArYa9GXwMkYsoQHdaJKrjUTek + +Parent transaction (spends coinbase of block 1): +02000000000101f86fd1d0db3ac5a72df968622f31e6b5e6566a09e29206d7c7a55df90e181de800000000171600141fb9623ffd0d422eacc450fd1e967efc477b83ccffffffff0580b2e60e00000000220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b94680b2e60e0000000017a9146a235d064786b49e7043e4a042d4cc429f7eb6948780b2e60e00000000160014fbb4db9d85fba5e301f4399e3038928e44e37d3280b2e60e0000000017a9147ecd1b519326bc13b0ec716e469b58ed02b112a087f0006bee0000000017a914f856a70093da3a5b5c4302ade033d4c2171705d387024730440220696f6cee2929f1feb3fd6adf024ca0f9aa2f4920ed6d35fb9ec5b78c8408475302201641afae11242160101c6f9932aeb4fcd1f13a9c6df5d1386def000ea259a35001210381d7d5b1bc0d7600565d827242576d9cb793bfe0754334af82289ee8b65d137600000000 +``` + +### Funding transaction (spends parent's outputs): + +Locktime: 618013 +Feerate: 253 sat/kiloweight +Opener's `funding_satoshi`: 4 0000 0000 sat +Accepter's `funding_satoshi`: 4 0000 0000 sat + +Inputs: +``` +4303ca8ff10c6c345b9299672a66f111c5b81ae027cc5b0d4d39d09c66b032b9 0 + witness_data: + preimage: 20 68656c6c6f2074686572652c2074686973206973206120626974636f6e212121 + witness_script: 27 82012088a820add57dfe5277079d069ca4ad4893c96de91f88ffb981fdc6a2a34d5336c66aff87 + scriptPubKey: 0020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b946 + address: bcrt1qlky6eaj5sh0cj7tanwnm573nvf9vg3f0qrdssyrlxsjh6vl9h9rql40v2g + +4303ca8ff10c6c345b9299672a66f111c5b81ae027cc5b0d4d39d09c66b032b9 1 + redeemScript: 0020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b946 + witness_data: + preimage: 20 68656c6c6f2074686572652c2074686973206973206120626974636f6e212121 + witness_script: 27 82012088a820add57dfe5277079d069ca4ad4893c96de91f88ffb981fdc6a2a34d5336c66aff87 + scriptPubKey: a9146a235d064786b49e7043e4a042d4cc429f7eb69487 + address: 2N2vRyi3cm5VYpw218MJJrJWK1Jd4qbaefW + +4303ca8ff10c6c345b9299672a66f111c5b81ae027cc5b0d4d39d09c66b032b9 2 + pubkey: 034695f5b7864c580bf11f9f8cb1a94eb336f2ce9ef872d2ae1a90ee276c772484 + privkey: cUM8Dr33wK4uFmw3Tz8sbQ7BiBNgX5BthRurU7RkgXVvNUPcWrJf + witness_program: fbb4db9d85fba5e301f4399e3038928e44e37d32 + scriptPubKey: 0014fbb4db9d85fba5e301f4399e3038928e44e37d32 + address: bcrt1qlw6dh8v9lwj7xq058x0rqwyj3ezwxlfjxsy7er + +4303ca8ff10c6c345b9299672a66f111c5b81ae027cc5b0d4d39d09c66b032b9 3 + pubkey: 034695f5b7864c580bf11f9f8cb1a94eb336f2ce9ef872d2ae1a90ee276c772484 + privkey: cUM8Dr33wK4uFmw3Tz8sbQ7BiBNgX5BthRurU7RkgXVvNUPcWrJf + redeemScript: 0014fbb4db9d85fba5e301f4399e3038928e44e37d32 + witness_program: fbb4db9d85fba5e301f4399e3038928e44e37d32 + scriptPubKey: a9147ecd1b519326bc13b0ec716e469b58ed02b112a087 + address: 2N4ogqX3kaLTT2jjxi18nAiyWdwKtE5PxLF +``` + +Expected Opener's `tx_add_input` (inputs 0+1 above): +``` + num_inputs: 2 + tx_add_input:[ + { + channel_id: xxx, + serial_id: 10, + prevtx_len: 353, + prevtx: 02000000000101f86fd1d0db3ac5a72df968622f31e6b5e6566a09e29206d7c7a55df90e181de800000000171600141fb9623ffd0d422eacc450fd1e967efc477b83ccffffffff0580b2e60e00000000220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b94680b2e60e0000000017a9146a235d064786b49e7043e4a042d4cc429f7eb6948780b2e60e00000000160014fbb4db9d85fba5e301f4399e3038928e44e37d3280b2e60e0000000017a9147ecd1b519326bc13b0ec716e469b58ed02b112a087f0006bee0000000017a914f856a70093da3a5b5c4302ade033d4c2171705d387024730440220696f6cee2929f1feb3fd6adf024ca0f9aa2f4920ed6d35fb9ec5b78c8408475302201641afae11242160101c6f9932aeb4fcd1f13a9c6df5d1386def000ea259a35001210381d7d5b1bc0d7600565d827242576d9cb793bfe0754334af82289ee8b65d137600000000 +, + prev_vout: 0, + sequence: 4294967293, + script_sig_len: 0, + script_sig: null + },{ + channel_id: xxx, + serial_id: 20, + prevtx_len: 353, + prevtx: 02000000000101f86fd1d0db3ac5a72df968622f31e6b5e6566a09e29206d7c7a55df90e181de800000000171600141fb9623ffd0d422eacc450fd1e967efc477b83ccffffffff0580b2e60e00000000220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b94680b2e60e0000000017a9146a235d064786b49e7043e4a042d4cc429f7eb6948780b2e60e00000000160014fbb4db9d85fba5e301f4399e3038928e44e37d3280b2e60e0000000017a9147ecd1b519326bc13b0ec716e469b58ed02b112a087f0006bee0000000017a914f856a70093da3a5b5c4302ade033d4c2171705d387024730440220696f6cee2929f1feb3fd6adf024ca0f9aa2f4920ed6d35fb9ec5b78c8408475302201641afae11242160101c6f9932aeb4fcd1f13a9c6df5d1386def000ea259a35001210381d7d5b1bc0d7600565d827242576d9cb793bfe0754334af82289ee8b65d137600000000 + prev_vout: 1, + sequence: 4294967293, + script_sig_len: 68, + script_sig: 0020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b946 + } + ] +``` + +Expected Accepter's `tx_add_input` (inputs 2+3 above): +``` + num_inputs: 2 + tx_add_input:[ + { + channel_id: xxx, + serial_id: 11, + prevtx_len: 353, + prevtx: 02000000000101f86fd1d0db3ac5a72df968622f31e6b5e6566a09e29206d7c7a55df90e181de800000000171600141fb9623ffd0d422eacc450fd1e967efc477b83ccffffffff0580b2e60e00000000220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b94680b2e60e0000000017a9146a235d064786b49e7043e4a042d4cc429f7eb6948780b2e60e00000000160014fbb4db9d85fba5e301f4399e3038928e44e37d3280b2e60e0000000017a9147ecd1b519326bc13b0ec716e469b58ed02b112a087f0006bee0000000017a914f856a70093da3a5b5c4302ade033d4c2171705d387024730440220696f6cee2929f1feb3fd6adf024ca0f9aa2f4920ed6d35fb9ec5b78c8408475302201641afae11242160101c6f9932aeb4fcd1f13a9c6df5d1386def000ea259a35001210381d7d5b1bc0d7600565d827242576d9cb793bfe0754334af82289ee8b65d137600000000 + prev_vout: 2, + script_sig_len: 0, + script_sig: null + },{ + channel_id: xxx, + serial_id: 17, + prevtx_len: 353, + prevtx: 02000000000101f86fd1d0db3ac5a72df968622f31e6b5e6566a09e29206d7c7a55df90e181de800000000171600141fb9623ffd0d422eacc450fd1e967efc477b83ccffffffff0580b2e60e00000000220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b94680b2e60e0000000017a9146a235d064786b49e7043e4a042d4cc429f7eb6948780b2e60e00000000160014fbb4db9d85fba5e301f4399e3038928e44e37d3280b2e60e0000000017a9147ecd1b519326bc13b0ec716e469b58ed02b112a087f0006bee0000000017a914f856a70093da3a5b5c4302ade033d4c2171705d387024730440220696f6cee2929f1feb3fd6adf024ca0f9aa2f4920ed6d35fb9ec5b78c8408475302201641afae11242160101c6f9932aeb4fcd1f13a9c6df5d1386def000ea259a35001210381d7d5b1bc0d7600565d827242576d9cb793bfe0754334af82289ee8b65d137600000000 + prev_vout: 3, + script_sig_len: 22, + script_sig: 0014fbb4db9d85fba5e301f4399e3038928e44e37d32 + } + ] +``` + +Outputs: (scriptPubKeys) +``` +# opener's change address +pubkey: 0206e626a4c6d4392d4030bc78bd93f728d1ba61214a77c63adc17d71e32ded3df +# privkey: cSpC1KYEV1vsUFBwTdcuRkncbwfipY1m5zuQ9CjgAYwiVvbQ4fc1 +scriptPubKey: 00141ca1cca8855bad6bc1ea5436edd8cff10b7e448b +address: bcrt1qrjsue2y9twkkhs022smwmkx07y9hu3ytshgjmj + +# accepter's change address +pubkey: 028f3978c211f4c0bf4d20674f345ae14e08871b25b2c957b4bdbd42e9726278fc +privkey: cQ1HXnbAE4wGhuB2b9rJEydV5ayeEmMqxf1dvHPZmyMTPkwvZJyg +scriptPubKey: 001444cb0c39f93ecc372b5851725bd29d865d333b10 +address: bcrt1qgn9scw0e8mxrw26c29e9h55asewnxwcsdxdp50 + +# the 2-of-2s +pubkey1: 0292edb5f7bbf9e900f7e024be1c1339c6d149c11930e613af3a983d2565f4e41e +pubkey2: 02e16172a41e928cbd78f761bd1c657c4afc7495a1244f7f30166b654fbf7661e3 +script_def: multi(2,0292edb5f7bbf9e900f7e024be1c1339c6d149c11930e613af3a983d2565f4e41e,02e16172a41e928cbd78f761bd1c657c4afc7495a1244f7f30166b654fbf7661e3) +script: 52210292edb5f7bbf9e900f7e024be1c1339c6d149c11930e613af3a983d2565f4e41e2102e16172a41e928cbd78f761bd1c657c4afc7495a1244f7f30166b654fbf7661e352ae +scriptPubKey: 0020297b92c238163e820b82486084634b4846b86a3c658d87b9384192e6bea98ec5 +address: bcrt1q99ae9s3czclgyzuzfpsggc6tfprts63uvkxc0wfcgxfwd04f3mzs3asq6l +``` + +Expected Opener's `tx_add_output`: + +``` + num_outputs: 2 + tx_add_output[ + { + channel_id: xxx, + serial_id: 30, + sats: 99999809 + scriptlen: 22 + script: 1600141ca1cca8855bad6bc1ea5436edd8cff10b7e448b + },{ + channel_id: xxx, + serial_id: 44, + sats: 800000000 + scriptlen: 34 + script: 220020297b92c238163e820b82486084634b4846b86a3c658d87b9384192e6bea98ec5 + } + ] +``` + +Expected Accepter's `tx_add_output`: + +``` + num_outputs: 1 + tx_add_output[ + { + channel_id: xxx, + serial_id: 33, + sats: 99999809 + scriptlen: 22 + script: 16001444cb0c39f93ecc372b5851725bd29d865d333b10 + } +``` + +Expected Fee Calculation: + +Opener's fees and change: +``` + initiator_weight = transaction_fields * 4 + + segwit_fields + + inputs * 4 + + funding_output * 4 + + change_output * 4 + + sum_max_witness_weight + + initiator_weight = 10 * 4 + + 2 + + (41 + 74) * 4 + + 43 * 4 + + 31 * 4 + + 148 + + initiator_weight = 946 + + initiator_fees = initiator_weight * feerate + initiator_fees = 946 * 253 / 1000 + initiator_fees = 239 sats + + change = total_funding + - funding_sats + - fees + + change = 5 0000 0000 + - 4 0000 0000 + - 239 + + change = 9999 9761 +``` + +Accepter's fees and change: +``` + contributor_weight = 2 * p2wpkh_input * 4 + + 2 * p2wpkh_output * 4 + + sum_max_witness_weight + + contributor_weight = (41 + 63) * 4 + + 31 * 4 + + 218 + + contributor_weight = 758 + + contributor_fees = contributor_weight * feerate + contributor_fees = 758 * 253 / 1000 + contributor_fees = 191 sats + + change = total_funding + - funding_sats + - fees + + change = 5 0000 0000 + - 4 0000 0000 + - 191 + + change = 9999 9809 + +``` + +Unsigned Funding Transaction: +``` +0200000004b932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430000000000ffffffffb932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430200000000ffffffffb932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430300000000ffffffffb932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430100000000ffffffff0341e0f505000000001600141ca1cca8855bad6bc1ea5436edd8cff10b7e448b11e0f5050000000016001444cb0c39f93ecc372b5851725bd29d865d333b100008af2f00000000220020297b92c238163e820b82486084634b4846b86a3c658d87b9384192e6bea98ec51d6e0900 +``` + +Signed Funding Transaction: +``` +TODO ``` # References diff --git a/09-features.md b/09-features.md index ea37b8b5e..0b321ebbf 100644 --- a/09-features.md +++ b/09-features.md @@ -40,6 +40,7 @@ The Context column decodes as follows: | 18/19 | `option_support_large_channel` | Can create large channels | IN | | [BOLT #2](02-peer-protocol.md#the-open_channel-message) | | 20/21 | `option_anchor_outputs` | Anchor outputs | IN | `option_static_remotekey` | [BOLT #3](03-transactions.md) | | 22/23 | `option_anchors_zero_fee_htlc_tx` | Anchor commitment type with zero fee HTLC transactions | IN | | [BOLT #3][bolt03-htlc-tx], [lightning-dev][ml-sighash-single-harmful]| +| 28/29 | `option_dual_fund` | Use v2 of channel open, enables dual funding | IN9 | `option_anchor_outputs`, `option_static_remotekey` | [BOLT #2](02-peer-protocol.md) | ## Requirements diff --git a/tools/spellcheck.sh b/tools/spellcheck.sh index fb309315f..709913db3 100755 --- a/tools/spellcheck.sh +++ b/tools/spellcheck.sh @@ -68,7 +68,8 @@ do -e 's/0x[a-fA-F0-9 ]\+//g' \ -e 's/[a-fA-F0-9]\{20,\}//g' \ -e 's/^ .*_htlcs//g' \ - -e 's/ \(bc\|tb\)1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]\+//g' \ + -e 's/ ln\(bc\|tb\)[0-9munp]*1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]\+//g' \ + -e 's/ \(bc\|tb\|bcrt\)1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]\+//g' \ -e 's/pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny//' \ -e 's/[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]\{20,\}//g' < $f | tee /tmp/`basename $f`.aspell | aspell -l en_US --home-dir ${homedir} list) if [ -n "$WORDS" ]; then