Skip to content

Channel establishment v2 (dual funding) - #239

Draft
erickcestari wants to merge 16 commits into
lnfuzz:masterfrom
erickcestari:channel-establishment-v2
Draft

erickcestari wants to merge 16 commits into
lnfuzz:masterfrom
erickcestari:channel-establishment-v2

Conversation

@erickcestari

@erickcestari erickcestari commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Adds fuzzing support for the BOLT 2 v2 channel establishment flow: open_channel2, interactive transaction construction, v2 commitment signatures and tx_signatures.

Protocol and transaction primitives

  • bolt: derive v2 channel ids from the revocation basepoints.
  • bitcoin: add raw transaction and sign-only RPCs.
  • channel_tx: add interactive transaction construction and compute the initiator's collaborative transaction fee.

IR and generators

  • smite-ir: add open_channel2, interactive transaction construction, v2 commitment and tx_signatures operations.
  • smite-ir: add the dual funding flow generator.
  • smite-ir-mutator: select the generator set per campaign.

Scenarios

  • Negotiate option_dual_fund with the peer.
  • Give the wallet more than one spendable UTXO.
  • Count the interactive tx replies the peer owes and stop receiving once the exchange concludes.

Depends on #222 , #221 and #240

For follow ups:

  • Enable dual funding for LDK (ldk-node doesn't expose an API to accept dual funding channels)
  • Add oracles
  • Add tx_remove_input and tx_remove_output to interactive-tx
  • Add interactive-tx rbf flow
  • Add splicing
  • Send tx_abort mid-negotiation

@erickcestari
erickcestari force-pushed the channel-establishment-v2 branch from 7ab8dfb to e18c1d1 Compare September 8, 2026 19:50
@erickcestari

Copy link
Copy Markdown
Contributor Author

This PR can be decomposed in multiple other smaller PRs if needed.

@erickcestari
erickcestari force-pushed the channel-establishment-v2 branch from e18c1d1 to ca525b5 Compare September 9, 2026 13:23
BOLT 2 derives both the temporary_channel_id and the channel_id of a
dual-funded channel from revocation basepoints rather than from the
funding outpoint.
Channel establishment v2 needs the previous transaction bytes for
tx_add_input and our own witnesses for tx_signatures, which the wallet
can only produce as a partial signing of the shared transaction.
A dual-funded funding transaction holds whatever the program negotiated:
no inputs, inputs the wallet cannot sign, a lock time in the future or an
output that breaks a consensus rule. None of these is a harness failure.
Classify sendrawtransaction rejections, and keep a policy-rejected
transaction for mining later only if a block would accept it.
SharedTransaction accumulates the inputs and outputs both peers add and
remove by serial_id and assembles the BOLT 2 shared transaction, with
the initiator's fee computed per BOLT 3 Appendix G.
TxExchange drives a SharedTransaction from the messages sent and
received, queuing unanswered sends so a program that sends several
messages before reading a reply still settles which tx_complete
concluded the exchange.
Negotiations are keyed by temporary_channel_id and addressable by the
derived channel_id every later message carries.
BOLT 2 makes the two channel establishment flows mutually exclusive on
one connection, so the v2 flow needs its own post-init snapshot that
keeps option_dual_fund, and CLN and Eclair need to advertise it.
Each tx_add_input locks the coin it selects, so a program contributing
several inputs needs several mature coinbase outputs.
The first half of the channel establishment v2 flow: build and send
open_channel2, receive accept_channel2 and extract its fields, and
derive the temporary_channel_id and channel_id BOLT 2 computes from the
revocation basepoints.

New variants are appended to Operation: it is postcard-encoded by
declaration index, so inserting mid-enum would make existing corpus
entries decode as different operations.
Contribute inputs and outputs to the shared transaction, remove them,
send tx_complete and read the peer's replies, then rebuild the funding
transaction from the negotiation. A receive reads only while the peer
owes a reply, and building from the negotiation settles the owed
replies first, so what is built is what the peer agreed to.
Exchange the initial commitment_signed over the negotiated funding
transaction, then tx_signatures in the order BOLT 2 prescribes: the peer
that contributed less signs first, ties broken by node_id. The peer's
witnesses are applied when the funding transaction is broadcast, since
our wallet cannot sign its inputs.
One linear script from open_channel2 through channel_ready, with every
interactive tx send paired with a receive.
BOLT 2 makes the two channel establishment flows mutually exclusive on
one connection, so a campaign only wants the generators its snapshot can
act on. SMITE_IR_GENERATORS picks v1, v2 or all, and smitebot sets it
from the scenario name.
@erickcestari
erickcestari force-pushed the channel-establishment-v2 branch from 8f4fb9a to 32337dc Compare September 15, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant