Skip to content

Commit 2c1b500

Browse files
committed
Make splice_locked atomic on reestablish
If one side sent `splice_locked` and the other side is ready to send its own `splice_locked` while they are disconnected, this creates a race condition on reestablish because `splice_locked` is retransmitted after `channel_reestablish`, and other channel updates can be inserted by the other node before receiving `splice_locked`. This will be an issue for taproot channels, because nonces will be missing. This race condition is described in more details in #1223. We fix this race condition by adding a TLV to `channel_reestablish` that provides information about the latest locked transaction. This additional information also makes it easier to detect when we need to retransmit our previous `splice_locked`.
1 parent 82f6862 commit 2c1b500

File tree

2 files changed

+46
-78
lines changed

2 files changed

+46
-78
lines changed

02-peer-protocol.md

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,7 @@ the locked transaction replaces the previous funding transaction.
19441944

19451945
Each node:
19461946
- If any splice transaction reaches acceptable depth:
1947-
- MUST send `splice_locked`.
1947+
- MUST send `splice_locked` with the `txid` of that transaction.
19481948

19491949
Once a node has sent and received `splice_locked`:
19501950
- MUST consider the locked splice transaction to be the new funding
@@ -1954,18 +1954,6 @@ Once a node has sent and received `splice_locked`:
19541954
- MUST send `announcement_signatures` with `short_channel_id` matching
19551955
the locked splice transaction.
19561956

1957-
On reconnection:
1958-
- MUST retransmit its last `splice_locked` if the `commitment_number`
1959-
is the same as before sending `splice_locked`.
1960-
1961-
##### Rationale
1962-
1963-
If a disconnection happens, nodes cannot know whether their peer received
1964-
their `splice_locked` message, so they retransmit it. Redundant messages
1965-
are harmless and can be safely ignored. If updates to the commitment have
1966-
been signed, this implicitly acknowledges that `splice_locked` has been
1967-
received and doesn't need to be retransmitted.
1968-
19691957
## Channel Close
19701958

19711959
Nodes can negotiate a mutual close of the connection, which unlike a
@@ -2938,6 +2926,9 @@ messages are), they are independent of requirements here.
29382926
1. type: 0 (`next_funding`)
29392927
2. data:
29402928
* [`sha256`:`next_funding_txid`]
2929+
1. type: 2 (`my_current_funding_locked`)
2930+
2. data:
2931+
* [`sha256`:`my_current_funding_locked_txid`]
29412932

29422933
`next_commitment_number`: A commitment number is a 48-bit
29432934
incrementing counter for each commitment transaction; counters
@@ -2996,6 +2987,13 @@ The sending node:
29962987
- MUST set `next_commitment_number` to the commitment number of the `commitment_signed` it sent.
29972988
- otherwise:
29982989
- MUST NOT set `next_funding_txid`.
2990+
- if `option_splice` was negotiated:
2991+
- MUST set `my_current_funding_locked` to the `funding_txid` of the most recent splice
2992+
transaction for which:
2993+
- it has already sent `splice_locked` or it is ready to send `splice_locked` after `channel_reestablish`.
2994+
- AND it has already received `splice_locked` from the remote node.
2995+
- if no splice transaction was ever made on the channel:
2996+
- MUST set `my_current_funding_locked` to the initial `funding_txid` of the channel.
29992997

30002998
A node:
30012999
- if `next_commitment_number` is 1 in both the `channel_reestablish` it
@@ -3064,11 +3062,16 @@ A receiving node:
30643062
this funding transaction.
30653063

30663064
A receiving node:
3067-
- MUST send `splice_locked` for the most recent splice transaction that reached
3068-
acceptable depth, unless `splice_locked` was already sent for this transaction
3069-
and `next_commitment_number` is strictly greater than the `commitment_number + 1`
3070-
that was used when `splice_locked` was previously sent (which indicates that
3071-
the previous `splice_locked` was received).
3065+
- if `my_current_funding_locked` is set:
3066+
- MUST process `my_current_funding_locked_txid` as if it was receiving
3067+
`splice_locked` for this `txid`, and thus discard the previous funding
3068+
transaction and RBF attempts if it has previously sent its own
3069+
`splice_locked` for that `txid`.
3070+
- if `my_current_funding_locked_txid` does not match the most recent
3071+
`splice_locked` it has sent:
3072+
- MUST retransmit `splice_locked`.
3073+
- otherwise:
3074+
- MUST NOT retransmit `splice_locked`.
30723075

30733076
A node:
30743077
- MUST NOT assume that previously-transmitted messages were lost,
@@ -3129,16 +3132,6 @@ operation, which is known to have begun after a `commitment_signed` has been
31293132
received — hence, the test for a `next_commitment_number` greater
31303133
than 1.
31313134

3132-
A previous draft insisted that the funder "MUST remember ...if it has
3133-
broadcast the funding transaction, otherwise it MUST NOT": this was in
3134-
fact an impossible requirement. A node must either firstly commit to
3135-
disk and secondly broadcast the transaction or vice versa. The new
3136-
language reflects this reality: it's surely better to remember a
3137-
channel which hasn't been broadcast than to forget one which has!
3138-
Similarly, for the fundee's `funding_signed` message: it's better to
3139-
remember a channel that never opens (and times out) than to let the
3140-
funder open it while the fundee has forgotten it.
3141-
31423135
A node, which has somehow fallen
31433136
behind (e.g. has been restored from old backup), can detect that it has fallen
31443137
behind. A fallen-behind node must know it cannot broadcast its current
@@ -3154,6 +3147,15 @@ interactive transaction construction, or safely abort that transaction
31543147
if it was not signed by one of the peers, who has thus already removed
31553148
it from its state.
31563149

3150+
`my_current_funding_locked` allows peers to detect that their `splice_locked`
3151+
was lost during the disconnection and must be retransmitted. When a splice
3152+
transaction reaches acceptable depth while peers are disconnected, it also
3153+
allows locking that splice transaction immediately after `channel_reestablish`
3154+
instead of waiting for the `splice_locked` message, which could otherwise
3155+
create a race condition with channel updates. For more details about this
3156+
race condition, see [this example](./bolt02/splicing-test.md#disconnection-with-concurrent-splice_locked).
3157+
Redundant `splice_locked` messages are harmless and can be safely ignored.
3158+
31573159
# Authors
31583160

31593161
[ FIXME: Insert Author List ]

bolt02/splicing-test.md

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -627,17 +627,17 @@ Alice initiates a splice, but disconnects before Bob receives her tx_signatures
627627
### Disconnection with concurrent `splice_locked`
628628

629629
In this scenario, disconnections happen while nodes are exchanging `splice_locked`.
630-
The `splice_locked` message must be retransmitted on reconnection until new commitments have been signed.
630+
The `splice_locked` message must be retransmitted on reconnection if it wasn't previously received.
631+
When `my_current_funding_locked` is set, this lets nodes immediately lock the latest splice transaction.
631632

632633
```text
633634
Initial active commitments:
634635
635-
commitment_number = 10
636636
+------------+
637637
| FundingTx1 |
638638
+------------+
639639
640-
Alice initiates a splice, but disconnects before Bob receives her splice_locked:
640+
Alice initiates a splice, but disconnections happen when exchanging splice_locked:
641641
642642
Alice Bob
643643
| stfu |
@@ -668,77 +668,43 @@ Alice initiates a splice, but disconnects before Bob receives her splice_locked:
668668
|---------------------X |
669669
| | Active commitments:
670670
| |
671-
| | commitment_number = 10
672671
| | +------------+ +------------+
673672
| | | FundingTx1 |------->| FundingTx2 |
674673
| | +------------+ +------------+
675674
| |
676-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 11, next_revocation_number = 10
675+
| channel_reestablish | next_funding_txid = null, my_current_funding_locked_txid = funding_tx1
677676
|----------------------------->|
678-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 11, next_revocation_number = 10
677+
| channel_reestablish | next_funding_txid = null, my_current_funding_locked_txid = funding_tx1
679678
|<-----------------------------|
680679
| splice_locked |
681680
|----------------------------->|
682-
| splice_locked |
681+
| splice_locked | At that point, Bob has locked funding_tx2, but Alice doesn't know it because she hasn't received splice_locked yet.
683682
| X----------------------|
684683
| |
685-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 11, next_revocation_number = 10
684+
| channel_reestablish | next_funding_txid = null, my_current_funding_locked_txid = funding_tx1
686685
|----------------------------->|
687-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 11, next_revocation_number = 10
688-
|<-----------------------------|
689-
| splice_locked |
690-
|----------------------------->|
691-
| splice_locked |
686+
| channel_reestablish | next_funding_txid = null, my_current_funding_locked_txid = funding_tx2
692687
|<-----------------------------|
688+
| | Alice doesn't need to retransmit splice_locked, since Bob's my_current_funding_locked_txid indicates that he received it.
689+
| | Bob's my_current_funding_locked_txid lets Alice know that Bob has locked funding_tx2 while they were disconnected and will send his splice_locked.
690+
| | She can thus immediately lock it as well even though she hasn't received yet Bob's splice_locked.
691+
| |
693692
| | Active commitments:
694-
| |
695-
| | commitment_number = 10
693+
| |
696694
| | +------------+
697695
| | | FundingTx2 |
698696
| | +------------+
699-
| update_add_htlc |
700-
|----------------------X |
701-
| commit_sig |
702-
|----------------------X |
703697
| |
704-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 11, next_revocation_number = 10
705-
|----------------------------->|
706-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 11, next_revocation_number = 10
707-
|<-----------------------------|
708-
| splice_locked |
709-
|----------------------------->|
710-
| splice_locked |
711-
|<-----------------------------|
712698
| update_add_htlc |
713699
|----------------------------->|
714-
| commit_sig |
700+
| commit_sig | Alice doesn't need to sent commit_sig for funding_tx1 since funding_tx2 was locked.
715701
|----------------------------->|
702+
| splice_locked | Bob's splice_locked is sent concurrently with Alice's update_add_htlc and commit_sig: this is fine.
703+
|<-----------------------------|
716704
| revoke_and_ack |
717705
|<-----------------------------|
718706
| commit_sig |
719707
|<-----------------------------|
720708
| revoke_and_ack |
721709
|----------------------------->|
722-
| | Active commitments:
723-
| |
724-
| | commitment_number = 11
725-
| | +------------+
726-
| | | FundingTx2 |
727-
| | +------------+
728-
| |
729-
| | A new commitment was signed, implicitly acknowledging splice_locked.
730-
| | We thus don't need to retransmit splice_locked on reconnection.
731-
| update_add_htlc |
732-
|----------------------X |
733-
| commit_sig |
734-
|----------------------X |
735-
| |
736-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 12, next_revocation_number = 11
737-
|----------------------------->|
738-
| channel_reestablish | next_funding_txid = null, next_commitment_number = 12, next_revocation_number = 11
739-
|<-----------------------------|
740-
| update_add_htlc |
741-
|----------------------------->|
742-
| commit_sig |
743-
|----------------------------->|
744710
```

0 commit comments

Comments
 (0)