1 of 20

Eltoo on LN: Idea to Implementation

Greg “instagibbs” Sanders

2 of 20

Idea

latest state output

funding output

“rebinding”

Update transaction

settlement transaction

3 of 20

  • NOINPUT -> ANYPREVOUT(ANYSCRIPT)
    • *Intentional* signature replay, spending *any* prior state output
  • No asymmetrical state
  • Simple state replacement challenge/response
    • O(1) watchtowers/nodes
  • N-Party channels trivially(?) work
  • No punishment mechanism
    • Incentive is uptime + unilateral fees
  • Longer HTLC timeouts*

Idea

4 of 20

Building out end to end specification/implementation of eltoo channels for Core Lightning, with feedback from community and Inquisition signet/Liquid operation

Deciding if BIP118(ANYPREVOUT) sufficient for useful eltoo, or are more expressive changes required

Seeing how simple can we make the protocol

Project Goals

5 of 20

BIP118

Use Taproot’s “unknown pubkey” type to opt into new signature hash that omits prevout(and sometimes execution script/value)

Consensus Changes

6 of 20

Package Relay: Allow child to pay for 0/low-fee parent to get into mempool

Anti-Pinning Measures: “[bitcoin-dev] New transaction policies (nVersion=3) for contracting protocols”

Assumed Mempool Changes

7 of 20

Non-empty Taproot Annex relay, ala OP_RETURN (or a spare 32 bytes otherwise lying around committed to by signatures?)

“Ephemeral Anchors”:

  • An OP_TRUE output that MUST be spent in relay package
    • Anyone can bump
    • Robust bumping even without other outputs timelocked
  • Any satoshi value allowed, even 0

Assumed Mempool Changes

8 of 20

Transaction Flow

> Alice & Bob do N channel updates

> Alice gets Update T-1 mined

> Bob submits Update T+1 within shared_delay blocks

> Bob sweeps HTLC/funds after shared_delay blocks

9 of 20

HTLC Forwards

LN Today

Eltoo-based Draft BOLT:

Two unexpected tricks required

10 of 20

State Output: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

EXPR_SETTLE(n) = <CovSig(TL(n))> <1_G> OP_CHECKSIG

EXPR_UPDATE(x) = and(pk(aggregated_key),after(TL(x)))

Transaction Structure

11 of 20

State Output: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

EXPR_SETTLE(n) = <CovSig(TL(n))> <1_G> OP_CHECKSIG

EXPR_UPDATE(x) = and(pk(aggregated_key),after(TL(x)))

Transaction Structure

Alice+Bob MuSig2, commit to update and settle path

12 of 20

State Output: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

EXPR_SETTLE(n) = <CovSig(TL(n))> <1_G> OP_CHECKSIG

EXPR_UPDATE(x) = and(pk(aggregated_key),after(TL(x)))

Transaction Structure

Signature-in-script, since ANYPREVOUTANYSCRIPT omits script as well

CTV-like trick to avoid “hostage” situation with no message roundtrips

13 of 20

State Output: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

EXPR_SETTLE(n) = <CovSig(TL(n))> <1_G> OP_CHECKSIG

EXPR_UPDATE(x) = and(pk(aggregated_key),after(TL(x)))

Transaction Structure

Public key generator G, privkey of “1”

“Pre-signed” by anyone at any time with access to settlement state

14 of 20

State Output: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

EXPR_SETTLE(n) = <CovSig(TL(n))> <1_G> OP_CHECKSIG

EXPR_UPDATE(x) = and(pk(aggregated_key),after(TL(x)))

Transaction Structure

Update path using Alice+Bob MuSig2 key, anything “newer” can spend this

15 of 20

State Output: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

EXPR_SETTLE(n) = <CovSig(TL(n))> <1_G> OP_CHECKSIG

EXPR_UPDATE(x) = and(pk(aggregated_key),after(TL(x)))

Transaction Structure

Oops: If old update tx gets mined, O(1) honest node can’t recompute this, as it has forgotten old state! No way of making control block to spend via update path :(

16 of 20

EXPR_SETTLE(n): <CovSig(TL(n))> <1_G> OP_CHECKSIG

  • Embed TapLeaf hash of EXPR_SETTLE in every Update Transaction’s state input annex
    • Old update transaction carries necessary data to spend its state output, can be directly copied into control block
    • 32 weight units extra for unilateral close case
  • Graftroot/delegation would also fix this
  • Or go back to two normal signatures and 1.5 round-trips

Transaction Structure

17 of 20

  • Draft BOLTs: https://github.com/instagibbs/bolts/tree/eltoo_draft
  • Taproot support
  • MuSig2 support
  • Channel Openings (single funded)
  • Invoices/HTLCs/payment hops

What’s Working

18 of 20

  • On chain resolution of unilateral closes
  • Cooperative channel closings
  • Channel announcements
  • Connection re-establishment

What’s Not

19 of 20

LN today is great!

Complexity is the enemy of security

Consensus BIP mistakes tend to be discovered once built on

Wallets 🤝 V3 transactions + Ephemeral Anchors

Final Thoughts

20 of 20

Special thanks to:

Blockstream

And discussion/review: AJ, remeyers, ariard, darosior, glozow, cdecker, tbast, rusty, sanket1729, and many others

##eltoo on libera.chat gsanders@blockstream.com/@theinstagibbs

Thanks!