#1611·fiber

Terminal 0xfe settlement can leave an upstream TLC unreconciled after #1583

Author: gpBlockchainCreated Aug 7, 2026Updated Aug 7, 2026

Scenario

Topology: A-B-C-D, payment direction A -> D. The B-C channel is force-closed.

After the TLC expires, C-D completes RemoveTlc off-chain. The B-C TLC is settled on-chain, after which B is expected to propagate RemoveTlc to A-B.

The TLC on B-C is offered by B and received by C. After C claims its final-party balance, the remaining commitment-cell capacity, including the expired TLC, belongs to B. B can therefore complete settlement using terminal unlock 0xfe.

Intermittent failure

The result depends on B/C watchtower transaction ordering.

In the failed run:

  1. C first sends final-party 0xff transaction 0x43f2822701f2ea18141cd7cbc29bbf4737feedd57a809067b40a6a7f2cb342f4.
  2. B builds explicit TLC timeout transaction 0xbc365cd3b7ae9c083b40c59a232ae07a64e455406b042e2a25f2831acffec992 with unlock_type=0.
  3. The transaction is rejected: PoolRejectedRBF: current fee 869, expected >= 2172.
  4. B then consumes C's settlement output using terminal 0xfe transaction 0xcbc47f741c565657c9d053e6bf82cc6d394db5def6f6d666d97e7b3e2969c8bc.

The terminal 0xfe transaction settles all remaining capacity, including B's expired TLC, so the TLC is settled without a preimage.

After #1583, however, the watchtower skips final-party unlocks:

rust
if unlock.unlock_type >= 0xFE {
    continue;
}

No SettledWithoutPreimage resolution is recorded. The B-C channel repeatedly logs:

on-chain settlement reconciliation incomplete; keeping ONCHAIN_SETTLEMENT_CONFIRMED

B does not propagate RemoveTlc to A-B, and A's offered TLC remains locked.

In the successful run, B's explicit unlock_type=0 transaction enters the pool before C's final-party transaction. The TLC receives an explicit timeout resolution, B-C reconciliation completes, and B propagates RemoveTlc to A-B.

Before #1583, final-party 0xfe/0xff unlocks recorded the pending TLCs as on-chain settlements. #1583 changed this behavior to ignore final-party unlocks while binding settlement proofs to exact TLC identities. In this terminal-settlement path, the B-owned TLC is settled by the 0xfe sweep, but no corresponding exact TLC resolution is produced.

Failure sequence

mermaid
sequenceDiagram
    autonumber
    participant A
    participant B
    participant C
    participant D
    participant Chain as Mempool / chain
    participant WT as Watchtower

    A->>B: AddTlc
    B->>C: AddTlc
    C->>D: AddTlc

    Note over B,C: B-C is force-closed
    D-->>C: TLC expires
    C->>C: C-D completes RemoveTlc off-chain

    C->>Chain: Submit final-party 0xff
    B->>Chain: Submit explicit timeout transaction<br/>unlock_type = 0
    Chain--xB: Rejected by RBF<br/>insufficient fee

    B->>Chain: Submit terminal 0xfe
    Note over B,Chain: Settles all remaining capacity<br/>including B's expired TLC

    Chain-->>WT: Detect 0xfe settlement
    WT->>WT: unlock_type >= 0xfe<br/>continue
    Note right of WT: SettledWithoutPreimage<br/>is not recorded

    WT-->>B: Exact TLC resolution is missing
    B->>B: Reconciliation remains incomplete
    B->>B: Keep ONCHAIN_SETTLEMENT_CONFIRMED

    B--xA: RemoveTlc is not propagated
    Note over A,B: A-B offered TLC remains locked