Skip to content

Latest commit

 

History

History
369 lines (251 loc) · 15.6 KB

XX-eltoo-transactions.md

File metadata and controls

369 lines (251 loc) · 15.6 KB

BOLT #??: Bitcoin Transaction and Script Formats for Eltoo Channels

This details the exact format of on-chain transactions, which both sides need to agree on to ensure signatures are valid. This consists of the funding transaction output script, the update transactions, and the settlement transactions.

Table of Contents

Mempool Policy and Consensus Changes Required

The rest of the document presumes a specific set of mempool policy enhancements and consensus changes.

roughly detailed here.

The consensus assumptions are:

  1. These transactions assume BIP118 in its current written form.

The policy assumptions are:

  1. Package relay is implemented and deployed, as per this link
  2. Package RBF is adopted for rule#3 pinning mitigation.
  3. Ephemeral Anchors are implemented.
  4. Annex data is allowed, up to at least 33 bytes worth for our purposes. Should update to this format.
  5. Mitigation for ACP-style pinning on APO (how to stop 0-value junk inputs from being added to APO transactions?)

Transactions

Transaction Symmetry

The biggest difference between this BOLT and BOLT03 is the fact that channel updates now have symmetrical state.

Each party in the relevant channel has an identical view of the transactions being collaboratively created. This means that we no longer rely on revocation and punishment transactions to enforce correctness, but on-chain claim and response periods via two types of transactions:

  1. update transactions to make a "claim" of latest channel state
  2. settlement transactions to expand out payments once challenge phase ends.

Transaction Output Ordering

The same rules for output ordering from BOLT03 applies to update and settlement transactions at time of signing.

Rationale

Use of Taproot

All outputs except ephemeral anchors are pay-to-taprootBIP341 (P2TR) outputs. We are ommitting all non-script related witness stack items for brevity such as control block, inner pubkeys, et al.

A <> designates an empty vector as required for compliance with BIP342

All taproot leaf versions are 0xC0 unless stated otherwise.

Use of miniscript

Miniscript compatibille scripts are used whenever possible to avoid ambiguity in notation, and allow for further analysis.

Funding Transaction Output

  • The value is the channel capacity.

TL(n) = 500000000+o+n

  • Where o equals the state-masking offset(always 0 for now)

  • Where n equals the channel state version, starting at 0

  • The funding output script is a P2TR to:

sorted_pubkey1, sorted_pubkey2 = KeySort(<set of funding_pubkey fields negotiated>) aggregated_key = KeyAgg(sorted_pubkey1, sorted_pubkey2) tr(aggregated_key, EXPR_UPDATE(0))

  • where EXPR_UPDATE(x) =

<1> OP_CHECKSIGVERIFY <TL(x)> OP_CHECKLOCKTIMEVERIFY if x > 0 with the policy of and(pk(1),after(TL(x)))

else

<1> OP_CHECKSIG, in the case of x == 0 with the policy of pk(1)

  • Output descriptors as defined by BIP386 and abused by the author.

  • Where KeyAgg and KeySort are defined as per BIP-musig2.

Update Transaction

  • version: 3
  • locktime: TL(n), where n is the state number for this update transaction
  • txin count: 1
    • txin[0] outpoint: txid and output_index from last published state m output (can be 0, the funding output)
    • txin[0] sequence: 0xFFFFFFFD
    • txin[0] script bytes: 0
    • txin[0] witness:
      • annex: 0x50 followed by ''hashTapLeaf(0xC0 || compact_size(size of EXPR_SETTLE(m)) || EXPR_SETTLE(m))''
      • control block: 0xC0 marker for tapscript, internel public key, merkle proof unless spending funding tx
      • tapscript: EXPR_UPDATE(m+1)
      • signature_for_inner_pubkey
  • txout count: 2
    • txout[0] amount: 0
    • txout[0] script: OP_2 (ephemeral anchor)
    • txout[1] amount: the channel capacity
    • txout[1] script: tr(aggregated_key, {EXPR_UPDATE(n+1), EXPR_SETTLE(n)})

and where EXPR_SETTLE(n) =

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

where CovSig(x) is the SIGHASH_ALL|ANYPREVOUTANYSCRIPT signature of the corresponding settlement transaction with a locktime of x, and 1_G the 33-byte BIP118 public key matching the secp256k1 generator G, using the BIP340 "Default Signing" nonce derivation function, with no auxiliary input.

and where `signature_for_inner_pubkey uses SIGHASH_ALL|ANYPREVOUTANYSCRIPT.

Note that the locktime must increase monotonically as it's used as the consensus ratchet for allowing rebinding of updates.

FIXME Use some standardized annex formatting to avoid app/consensus collisions, aka Sunny Side of Annex

Rationale

Anyprevout style covenants are used in the update transaction taptree to avoid requiring additional communication round-trips for forwarding HTLC messages. If we required a standard MuSig2 signature for the settlement transaction, it would be unsafe to hand your counterparty both update and settlement signatures in one step, as the counterparty could ransom your funds by publishing a completed update transaction, and withhold the final settlement signature.

We use the public generator G as a "well known" point, where privkey is 1, so the signature can be recreated by any software, including watchtowers. The script does not need rotation since the signature is committed to directly in the script, and the signature directly commits to the settlement transaction, including the nlocktime which is unique per update in a given channel.

The annex is required to allow recovery of the control block to spend an invalidated update transaction with the latest update transaction, without requiring particpants to hold all invalidated settlement states forever. This is due to the signature that is included in the script, which cannot be otherwise deterministically regenerated without access to the full settlement state. Alternatively, we could add another round-trip to HTLC additions and forwards, as well as further complicate the protocol.

The "state-masking offset" is used to hide the total number of updates in the channel from blockchain observers. Future versions of this spec can introduce a randomized negotiation of this value.

The ephemeral anchor will always be of value 0(and the other non-0), so output sorting will result in the ephemeral anchor output being first.

Settlement Transaction

  • version: 3
  • locktime: corresponding update transaction's locktime
  • txin count: 1
    • txin[0] outpoint: txid and output_index from latest committed state n output
    • txin[0] sequence: set to shared_delay, initially set in channel open negotiation
    • txin[0] script bytes: 0
    • txin[0] witness:
      • control block: merkle proof
      • tapscript: EXPR_SETTLE(n)
      • (no additional witness data needed)

Note there may be additional attached transaction inputs due to the ANYPREVOUTANYSCRIPT signatures which can be used to attach fees during settlement.

Settlement Transaction Outputs

Since we are relying on the shared_delay timelock to ensure that the final update transaction confirmed on the blockchain is indeed the final update in the channel, we do not require revocation paths or additional delays to spend the outputs contained in the settlement transaction. We have no second-stage pre-signed transactions, simply outputs that can be spent by the authorized parties. For balance outputs, these can be immedietly spent by the owners. For HTLC outputs, these can be spent immediately once the receiving party obtains the preimage, or can be clawed back by the offerer once the CLTV of the output expires.

The lack of second-stage transactions means that HTLCs must have timeouts longer than the shared_delay timeout to ensure on-chain enforcement.

Alternative proposals such as layered commitments for eltoo have been proposed, but require increased complexity and additional layer violations.

The amounts for each output MUST be rounded down to whole satoshis. If this amount is less than the dust_limit_satoshis set by the owner of the output, the output MUST NOT be produced (thus the funds add to fees).

to_node Output

This output sends funds back to the owner of the satoshi amount. It can be claimed without delay. The output is a P2TR of the form:

rawtr(settlement_pubkey)

There are N copies of this output, one for each channel participant and their associated settlement_pubkey sent during channel negotiation.

Rationale

Ideally, we could directly use a raw script to allow maximal flexibility, but we do not want to ensure that all output scripts given are mempool-standard. We do not need one block relative timelock in scripts since we can no longer be pinned by package sizes(bip125 rule#3) or package limits thanks to V3 transactions and ephemeral anchors.

HTLC Outputs

The output encumbers funds to the receipient of the HTLC offer with a primage, or back to the offerer upon timeout. Unlike BOLT03, these require no second stage transactions, and can be signed at any point.

tr(aggregated_key, {EXPR_SUCCESS, EXPR_TIMEOUT})

where EXPR_SUCCESS =

<htlc_pubkey> OP_CHECKSIGVERIFY OP_SIZE <20> OP_EQUALVERIFY OP_HASH160 <H> OP_EQUAL

with a policy of and(pk(htlc_pubkey),hash160(H))

where H is the payment hash and htlc_pubkey the recipient pubkey

and EXPR_TIMEOUT =

<htlc_pubkey> OP_CHECKSIGVERIFY N OP_CHECKLOCKTIMEVERIFY

with policy of and(after(N),pk(htlc_pubkey))

where N is the HTLC expiry blockheight, and htlc_pubkey is the offerer's pubkey.

The key-spend path is currently unused.

The recipient node can redeem the HTLC with the witness:

<payment_preimage> <recipient_htlc_pubkey_signature>

And the offerer via:

<offerer_htlc_pubkey_signature>

on an otherwise valid transaction.

Ephemeral Anchor Output

A single shared anchor output, also known as ephemeral anchor, is attached to the settlement transaction. This MUST be spent in a relay package to be considered for block inclusion.

This output contains the scriptpubkey of:

OP_TRUE, the output value is the value of all the trimmed output values, summed.

This allows an "empty" spend of the output by anyone, and no known mempool malleabilty vectors.

There is no consensus-level fix for malleability with bare scripts that lack a sighash, so that is the best we are going to do without committing to an expensive script hash.

Trimmed Outputs

Outputs with value below dust_limit_satoshis should not be produced; these outputs that are not produced are termed "trimmed". A trimmed output is considered too small to be worth creating and is instead added to the anchor output's value to be used as CPFP fees.

Requirements

Fees are handled by spending outputs from the outputs of the settlement transaction, as the settlement transaction includes no fee itself. This relies on package relay and package CPFP.

The settlement transaction:

  • for every to_node output:
    • if the amount of any of the settlement transaction to_node outputs would be less than dust_limit_satoshis set by the channel negotiation:
      • MUST NOT contain that output.
    • otherwise:
  • for every HTLC:
    • if the HTLC amount would be less than dust_limit_satoshis:
      • MUST NOT contain that output.
    • otherwise:

Closing Transaction

Note that there are two possible variants for each node.

  • version: 3
  • locktime: 0
  • txin count: 1
    • txin[0] outpoint: txid and output_index from funding_created message
    • txin[0] sequence: 0xFFFFFFFF
    • txin[0] script bytes: 0
    • txin[0] witness: <signature_for_musig2_pubkey>
  • txout count: 0, 1 or 2
    • txout amount: final balance to be paid to one node
    • txout script: as specified in that node's scriptpubkey in its shutdown message

Requirements

Each node offering a signature:

  • MUST round each output down to whole satoshis.
  • MUST remove any output below its own dust_limit_satoshis.
  • MAY eliminate its own output.

Rationale

Contrary to ln-penalty based chanels, we have a shared dust_limit_satoshis and a symmetrical transaction. Users can still opt to remove their own output and the signature will indicate to the peer which variant has been used.

There will be at least one output, if the funding amount is greater than twice dust_limit_satoshis.

Fees

The settlement transaction contains no fees, so implementers must rely on CPFP of the single anchor output for propogation and timely inclusion into the blockchain.

Transaction replacement of the CPFP can be a way to increase the feerate of the overall package, even if a counterparty is making CPFP transactions.

Dust Limits

These are statically set at 330 satoshis.

Update and Settlement Transaction Construction

This section ties the previous sections together to detail the algorithm for constructing the update and settlement transactions for both peers: given that peer's dust_limit_satoshis:

Update Transaction

This transaction is relatively trivial to set up.

  1. Initialize the update transaction input, output, and locktime as specified in Update Transaction.

Settlement Transaction

  1. Initialize the settlement transaction input and locktime, as specified in Settlement Transaction.
  2. Calculate which committed HTLCs and to_node outputs need to be trimmed (see Trimmed Outputs).
  3. For every HTLC, if it is not trimmed, add an HTLC output.
  4. For every to_node output, if it is not trimmed, add a to_node output.
  5. Add a single ephemeral output anchor.
  6. Sort the outputs into BIP 69+CLTV order.

References

Authors

Greg Sanders gsanders87@gmail.com

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.