Skip to content

Instantly share code, notes, and snippets.

@RobinLinus
Last active May 4, 2026 01:26
Show Gist options
  • Select an option

  • Save RobinLinus/b9fcbb0e5de19ec6b9a80aa848a94253 to your computer and use it in GitHub Desktop.

Select an option

Save RobinLinus/b9fcbb0e5de19ec6b9a80aa848a94253 to your computer and use it in GitHub Desktop.
A Protocol for Zero-Confirmation Bitcoin Payments

Protocol for Zero-Confirmation Bitcoin Payments

Overview

This protocol lets a Bitcoin user make zero-confirmation payments while retaining a trustless unilateral exit path if the co-signing server disappears or refuses to cooperate.

  • The user keeps funds in a confirmed 2-of-2 multisig with a co-signing server.
  • The co-signer enforces a policy of not signing conflicting spends.
  • Recipients can accept zero-confirmation payments if they trust the co-signer's policy.
  • The user receives a pre-signed unilateral exit transaction before depositing funds.
  • That unilateral exit is gated by a separate "connector" UTXO with a relative timelock.
  • The connector ensures that the unilateral exit cannot confirm immediately.
  • Before signing any payment that creates a new change UTXO, the user first obtains a pre-signed exit transaction for that change UTXO.

The result is:

  • The sender cannot lose funds if the co-signer disappears.
  • The recipient can safely accept zero-confirmation payments under the co-signer trust assumption.
  • The long-lived funding UTXO does not need periodic on-chain refreshes.
  • The sender's trustless exit guarantee rolls forward across payments and change outputs.

Participants

  • User / Sender: The owner of the funds. Wants to make instant payments while retaining unilateral recovery if the co-signer stops cooperating.
  • Co-Signing Server: Co-signs payments from the user's 2-of-2 wallet, subject to an anti-double-spend policy. Trusted by recipients not to sign conflicting transactions. Not trusted with custody of funds.
  • Recipient: Accepts zero-confirmation payments, trusting the co-signer to enforce the anti-double-spend policy and to only sign when the exit delay is long enough for the recipient's transaction to confirm first.

Protocol Construction

The user's funds are held in a confirmed 2-of-2 multisig output:

funding_utxo = 2-of-2(user_key, cosigner_key)

Before the user deposits funds, the co-signer gives the user a pre-signed unilateral exit transaction. This exit transaction requires two inputs: the funding UTXO and a connector UTXO.

exit_tx:
  inputs:
    - funding_utxo
    - connector_utxo with nSequence = exit_delay
  outputs:
    - user recovery output

The co-signer's signature commits to both inputs and the connector's nSequence.

The connector UTXO does not exist initially and can hold a dust/minimal amount — it is purely a timelock mechanism, not a store of value. To begin the unilateral exit, the user must first create it on-chain using a kickoff transaction:

kickoff_tx -> connector_utxo

After the kickoff confirms, the connector's relative timelock begins. Once the delay expires, the user can broadcast the pre-signed exit transaction and recover funds.

Within a single funding chain, all exit transactions reference the same connector UTXO. When a payment spends a funding UTXO, the old exit transaction referencing it becomes invalid automatically — no revocation is needed. Only the exit for the current live UTXO can ever be used. If a user maintains multiple independent 2-of-2 UTXOs, each funding chain requires its own dedicated connector.

Why the Connector Is Needed

A plain 2-of-2 is not trustless for the user: if the co-signer disappears, funds are stuck. A pre-signed exit fixes this, but if the exit is immediately valid, the user can use it to double-spend against zero-confirmation recipients.

The connector solves this by introducing a consensus-enforced delay. The user has a pre-signed exit, but to use it they must first create the connector UTXO on-chain and then wait for the relative timelock to expire. As long as this delay exceeds the time needed for the recipient's payment to confirm, zero-confirmation recipients remain protected.

Why a Relative Timelock

An absolute timelock (e.g., "exit valid after block 900000") would require periodic on-chain refreshes as the timelock approaches. The connector avoids this: the exit delay is relative to the connector UTXO's confirmation, and the connector does not exist until the user starts the exit process. The funding UTXO can remain live indefinitely.

Taproot Requirement

The protocol requires Taproot (P2TR) outputs. In SegWit v0 (BIP 143), SIGHASH_NONE zeros out hashSequence, meaning the co-signer's signature would not commit to nSequence. A malicious user could change nSequence to 0 and bypass the delay entirely. Taproot (BIP 341) fixes this: SIGHASH_NONE still commits to sha_sequences, so the co-signer's signature binds the connector's relative timelock.

If SegWit v0 must be used, the delay must be enforced via OP_CHECKSEQUENCEVERIFY directly in the connector UTXO's script rather than relying on nSequence alone.


Setup

1. Key Exchange

The user and co-signer derive or exchange keys for a 2-of-2 multisig output. The user also creates a dedicated kickoff UTXO (ideally as an additional output of the funding transaction). This UTXO must be reserved and never spent for other purposes, since its txid:vout determines the connector's txid:vout, which is committed to in the pre-signed exit.

2. Co-Signer Pre-Signs the Exit

The co-signer signs an exit transaction spending both the funding UTXO and the connector UTXO (with its relative timelock). The user verifies that the exit transaction is valid and pays the user. Only after verification does the user deposit funds.

3. User Deposits Funds

The user funds the 2-of-2 multisig output. This deposit must be confirmed before zero-confirmation payments can be made.


Making a Zero-Confirmation Payment

The user asks the co-signer to co-sign a transaction spending from the current 2-of-2 UTXO, creating a recipient output and (optionally) a new 2-of-2 change output.

payment_tx:
  inputs:
    - old_2of2_utxo
  outputs:
    - recipient_output
    - change_2of2_utxo (if change exists)

The ordering is:

1. Construct payment transaction with recipient output and new 2-of-2 change output.
2. Ask co-signer to pre-sign an exit_tx for the new change output.
3. User verifies the change exit_tx pays them and is properly connector-gated.
4. User signs the payment transaction.
5. Co-signer signs the payment transaction.
6. Recipient receives the fully signed payment transaction and may accept it zero-conf.

Co-Signer Policy

Before signing a payment, the co-signer checks:

  1. The spent 2-of-2 UTXO belongs to the protocol.
  2. The payment does not conflict with any previously co-signed payment.
  3. The unilateral exit path has not already become dangerously active.
  4. The exit delay is long enough for the recipient's payment to confirm first.
  5. If the payment creates a new 2-of-2 change output, the co-signer first provides the user with a valid pre-signed exit for that change output.
  6. The transaction pays the intended recipient and returns change only to an approved 2-of-2 output.
  7. The fee policy is sufficient for confirmation within the safety window.

The recipient can accept the payment before confirmation because the co-signer will not sign a conflicting spend, and the sender's unilateral exit cannot confirm until after the connector delay.

Repeated Payments from Change

The user does not need to wait for change outputs to confirm before making another payment. Each payment rolls the state forward:

old_2of2_utxo -> recipient_output + new_2of2_change_utxo

Before signing the payment, the user obtains a pre-signed exit for the new change output. This allows repeated zero-confirmation payments without waiting for intermediate change outputs to confirm. Note that Bitcoin Core enforces a limit of 25 unconfirmed ancestors/descendants, so rapid-fire payments are bounded until a block confirms.


Security Model

Sender Safety

The protocol is trustless with respect to custody. The sender always holds a valid pre-signed exit transaction before funds enter any 2-of-2 output. If the co-signer disappears, the sender recovers funds by broadcasting the kickoff, waiting the delay, and broadcasting the exit.

The co-signer cannot steal funds (it has only one key in a 2-of-2). It can refuse service but cannot prevent eventual recovery. The co-signer affects payment liveness, not custody.

Recipient Safety

The recipient's zero-confirmation security depends on the co-signer. The recipient trusts the co-signer to:

  • not sign conflicting spends,
  • track which funding UTXOs have already been spent,
  • refuse to sign unsafe transactions,
  • check whether the exit path is active or dangerous,
  • only sign if the exit delay is long enough for the recipient's payment to confirm first,
  • enforce fee and confirmation assumptions appropriate for the chosen delay.

The recipient does not need to trust the user, and does not need custody trust in the co-signer. The recipient's risk is that the co-signer signs incorrectly, equivocates, loses state, or applies an unsafe policy.

Protocol Invariants

The user never signs a transaction that can place their funds into a 2-of-2 output unless they already possess a valid unilateral exit path for that output.

The co-signer never signs conflicting spends and only signs zero-conf payments when the unilateral exit delay is long enough for the recipient transaction to confirm first.

The connector ties these two invariants together: it lets the user hold a valid exit path without making that exit immediately confirmable.


Unilateral Exit Flow

If the co-signer refuses to sign or disappears:

  1. Broadcast kickoff transaction: Creates the connector UTXO. The kickoff cannot be RBF'd (changing the txid would invalidate the pre-signed exit), so it should include a CPFP-spendable output for fee-bumping if needed.
  2. Wait for connector delay: The relative timelock begins once the connector confirms.
  3. Broadcast exit transaction: Spends both the funding UTXO and the connector UTXO, paying the user's recovery address.

No fresh signature from the co-signer is needed.


Failure Cases

Co-Signer Disappears

The user broadcasts the kickoff, waits for the connector delay, and broadcasts the pre-signed exit. Funds are recovered after the delay.

Co-Signer Refuses to Sign a Payment

The user cannot make instant payments through that co-signer but can still unilaterally exit.

Co-Signer Refuses to Pre-Sign the Change Exit

The user must not sign the payment transaction. Signing without a change exit would forfeit the trustless recovery guarantee for the change. This is treated as a failed payment attempt.

Co-Signer Signs Conflicting Payments

Recipients can be harmed. Zero-confirmation security depends on the co-signer not equivocating and not losing signing state.

User Starts Unilateral Exit

The co-signer should stop signing unsafe zero-confirmation payments from that funding UTXO. Previously signed recipient payments should still have time to confirm before the exit can confirm, if the delay was properly chosen.

Fee Problems

If fees are too low, the recipient's transaction may not confirm before the exit delay expires. The co-signer's policy should account for fee conditions and may require sufficient fees, CPFP capability, or a longer exit delay.


On-Chain Cost

Multisig vs MuSig2

The 2-of-2 output can be implemented as either a standard multisig or a MuSig2 aggregated key.

  • Multisig: Simpler to implement and broadly supported by wallets. Requires two separate signatures on-chain, increasing witness size.
  • MuSig2: Produces a single aggregated signature indistinguishable from a regular single-key spend. This reduces on-chain footprint but requires additional off-chain communication rounds between the user and co-signer, and requires wallet support for the MuSig2 protocol.

MuSig2 is preferred when on-chain cost and privacy are priorities, since payment transactions are indistinguishable from ordinary single-key spends. The protocol is only revealed on-chain during a unilateral exit.

SIGHASH_NONE for the Exit Transaction

The co-signer can pre-sign the funding input of the exit transaction with SIGHASH_NONE, meaning the co-signer's signature does not commit to any outputs. At exit time, the user signs both the funding input (completing the 2-of-2) and the connector input, choosing the recovery address and fee rate then rather than locking them in at setup time.

The co-signer's signature still commits to both inputs and the connector's nSequence, preserving the connector-gated delay. The user's SIGHASH_ALL signature on the connector input locks in all outputs at broadcast time, preventing miners from tampering with them despite the co-signer's SIGHASH_NONE.


Extensions

Lightning Compatibility

The 2-of-2 funding UTXO is structurally identical to a Lightning channel funding output. If the co-signer also acts as a Lightning Service Provider (LSP), the user can construct ad-hoc payment channels from the existing funding UTXO to pay Lightning invoices, settling back to a plain 2-of-2 change output afterward. This allows the same wallet to serve both zero-conf on-chain payments and Lightning payments without separate channel management.


Assumptions

  • The initial funding transaction is confirmed before zero-confirmation payments are made.
  • The user has a valid pre-signed exit transaction before depositing funds.
  • The user obtains a valid pre-signed exit for each new change output before signing the transaction that creates it.
  • The connector UTXO can be created when needed.
  • The relative timelock is long enough to give recipient transactions time to confirm.
  • The co-signer maintains correct state and does not sign conflicting spends.
  • Recipients trust the co-signer's policy.
  • The user maintains a reserved kickoff UTXO that is never spent during normal operation.
  • Fee management is sufficient for payment and exit transactions to confirm when needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment