Skip to content

fix: distinguish dropped txs from mempool txs in esplora confirmations#169

Open
matthewjablack wants to merge 1 commit into
bennyhodl:masterfrom
matthewjablack:fix/dlc-input-closed-state
Open

fix: distinguish dropped txs from mempool txs in esplora confirmations#169
matthewjablack wants to merge 1 commit into
bennyhodl:masterfrom
matthewjablack:fix/dlc-input-closed-state

Conversation

@matthewjablack

@matthewjablack matthewjablack commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Root cause: get_transaction_confirmations in esplora.rs returned Ok(0) for both mempool txs and dropped/never-broadcast txs. With NB_CONFIRMATIONS=0, the manager's 0 >= 0 check always passed, promoting contracts through states even when their funding tx was never mined.

Changes

ddk/src/chain/esplora.rs — the core fix:

  • When the tx is unconfirmed (confirmed: false), call get_tx to check if it's actually in the mempool
  • If it exists in mempool: return Ok(0) (existing behavior)
  • If the tx is gone (dropped/never-broadcast): return Err(TransactionNotFound) instead of Ok(0)
  • Consumers can now distinguish mempool from dropped
  • Moved get_height() call inside the confirmed branch (avoids wasted call when unconfirmed)

ddk-manager/src/manager.rs — defense-in-depth + recovery:

  • close_contract / check_and_broadcast_refund / check_refund: use unwrap_or(0) since the tx may not exist yet (pre-broadcast)
  • check_confirmed_contract pending_close_txs: skip dropped txs via Err(_) => continue
  • check_for_spliced_contract: skip pre-close only when the splice fund tx is dropped (Err), not when it's in the mempool (Ok(0))
  • check_preclosed_contract: on confirmation error for splice closes (no attestations), revert to Confirmed instead of propagating
  • recover_incorrectly_closed_contracts: new periodic check that finds splice-closed contracts whose closing tx is gone and reverts them to Confirmed

Context

On testnet4 with NB_CONFIRMATIONS=0, a splice fund tx entered the mempool and ddk walked the parent contract Confirmed → PreClosed → Closed in a single periodic_check cycle. The splice tx was later dropped from mempool, but the contract was already Closed. Subsequent splice attempts failed at get_signature_for_dlc_input because it only accepts Confirmed contracts.

@matthewjablack matthewjablack force-pushed the fix/dlc-input-closed-state branch 2 times, most recently from 8bac293 to 9560027 Compare June 29, 2026 18:47
@matthewjablack matthewjablack changed the title fix: allow DLC input signing for closed/preclosed contracts fix: prevent incorrect contract closure from mempool-only splice txs Jun 29, 2026
@matthewjablack matthewjablack force-pushed the fix/dlc-input-closed-state branch 4 times, most recently from dc8a172 to acf1469 Compare June 29, 2026 21:27
@matthewjablack matthewjablack changed the title fix: prevent incorrect contract closure from mempool-only splice txs fix: distinguish dropped txs from mempool txs in esplora confirmations Jun 29, 2026
@matthewjablack matthewjablack force-pushed the fix/dlc-input-closed-state branch from acf1469 to 820fa8f Compare June 29, 2026 21:56
Root cause: get_transaction_confirmations returned Ok(0) for both
mempool txs and dropped/never-broadcast txs. With NB_CONFIRMATIONS=0,
the manager's `0 >= 0` check always passed, promoting contracts
through states even when their funding tx was never mined.

esplora.rs: when the tx is unconfirmed, call get_tx to check if it's
actually in the mempool. If the tx is gone, return a TransactionNotFound
error instead of Ok(0). This lets consumers distinguish mempool (Ok(0))
from dropped (Err).

manager.rs:
- close_contract / check_and_broadcast_refund / check_refund: use
  unwrap_or(0) since the tx may not exist yet (pre-broadcast)
- check_confirmed_contract pending_close_txs: skip dropped txs
- check_for_spliced_contract: only skip pre-close when the splice fund
  tx is dropped (Err), not when it is in mempool (Ok(0))
- check_preclosed_contract: on confirmation error for splice closes
  (no attestations), revert to Confirmed instead of propagating
- recover_incorrectly_closed_contracts: new periodic check that finds
  splice-closed contracts whose closing tx is gone and reverts them
@matthewjablack matthewjablack force-pushed the fix/dlc-input-closed-state branch from 820fa8f to def648e Compare June 29, 2026 22:00
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