Skip to content

Taker Client Fails to Recover from Transaction Broadcast Failure #1825

@DavidRajnoha

Description

@DavidRajnoha

Summary

When a taker client fails to broadcast a transaction due to spent inputs (bad-txns-inputs-missingorspent), the retry mechanism never triggers, leaving the client in a zombie state that polls indefinitely without recovery.

Disclaimer

The issue has been encountered within an emulated environment (https://github.com/DavidRajnoha/coinjoin-simulator) – the conditions under which the bug occurs (availability of makers, frequency of taker coinjoin requests) might be different from real environment.

Steps to reproduce

  1. Start tumbler/RPC coinjoin
  2. Maker's UTXO gets spent between negotiation and broadcast
  3. Broadcast fails: error pushing = -25 bad-txns-inputs-missingorspent
  4. RPC Client becomes unresponsive to further rpc commands

Probable root cause

Missing Callback in handle_unbroadcast_transaction()

Location: src/jmclient/taker.py:932-934

  if not self.push_ourselves():
      jlog.error("Failed to broadcast transaction: ")
      jlog.info(btc.human_readable_transaction(tx))
      # MISSING: self.on_finished_callback(False, fromtx=True)

When self-broadcast fails, the error is logged but on_finished_callback() is never called to trigger retry logic.

Compare to push() method (lines 981-982) which correctly handles failure:

  if not pushed:
      self.on_finished_callback(False, fromtx=True)  # Triggers retry

Issue 2: Flawed Stall Monitor Logic

Location: src/jmclient/client_protocol.py:645-652

  if not self.client.txid:
      jlog.info("Stall detected. Retrying transaction if possible ...")
      self.client.on_finished_callback(False, True, 0.0)
  else:
      jlog.info("Tx was already pushed; ignoring")

Problem: Assumes if txid is set, broadcast succeeded. However, txid is calculated and set before broadcast attempt (line 941 in push()), so it's set regardless of success/failure.

Logs

  06:13:01 [INFO]  all makers have sent their signatures
  06:13:02 [INFO]  txid = 8062310600b7db8f...  # txid set BEFORE broadcast
  06:16:02 [WARN]  error pushing = -25 bad-txns-inputs-missingorspent
  06:16:02 [ERROR] Failed to broadcast transaction:  # No callback triggered!
  06:30:00 [INFO]  STALL MONITOR: Tx was already pushed; ignoring  # Wrong!
  06:31:24 [DEBUG] rpc: getwalletinfo []  # Called by external client, polls forever...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions